breakpoint
64
Assets/Plugins/GameDesigner/Component/Client/ARPGcamera.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.Component
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
public class ARPGcamera : MonoBehaviour
|
||||
{
|
||||
public Transform target;
|
||||
public float targetHeight = 1.2f;
|
||||
public float distance = 4.0f;
|
||||
public float maxDistance = 20;
|
||||
public float minDistance = 1.0f;
|
||||
public float xSpeed = 500.0f;
|
||||
public float ySpeed = 120.0f;
|
||||
public float yMinLimit = -10;
|
||||
public float yMaxLimit = 70;
|
||||
public float zoomRate = 80;
|
||||
public float rotationDampening = 3.0f;
|
||||
public float x = 20.0f;
|
||||
public float y = 0.0f;
|
||||
public float aimAngle = 8;
|
||||
public KeyCode key = KeyCode.Mouse1;
|
||||
protected Quaternion aim;
|
||||
protected Quaternion rotation;
|
||||
private Vector3 position;
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (Input.GetKey(key) | key == KeyCode.None)
|
||||
{
|
||||
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
|
||||
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
|
||||
}
|
||||
|
||||
distance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(distance);
|
||||
distance = Mathf.Clamp(distance, minDistance, maxDistance);
|
||||
|
||||
y = ClampAngle(y, yMinLimit, yMaxLimit);
|
||||
|
||||
// Rotate Camera
|
||||
rotation = Quaternion.Euler(y, x, 0);
|
||||
transform.rotation = rotation;
|
||||
|
||||
aim = Quaternion.Euler(y - aimAngle, x, 0);
|
||||
|
||||
//Camera Position
|
||||
position = target.position - (rotation * Vector3.forward * distance + new Vector3(0, -targetHeight, 0));
|
||||
transform.position = position;
|
||||
}
|
||||
|
||||
static float ClampAngle(float angle, float min, float max)
|
||||
{
|
||||
if (angle < -360)
|
||||
angle += 360;
|
||||
if (angle > 360)
|
||||
angle -= 360;
|
||||
return Mathf.Clamp(angle, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,22 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 只显示不能修改的属性
|
||||
/// </summary>
|
||||
public class DisplayOnly : PropertyAttribute
|
||||
{
|
||||
public string text;
|
||||
public DisplayOnly() { }
|
||||
public DisplayOnly(string text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///定义多选属性
|
||||
///</summary>
|
||||
public class EnumFlags : PropertyAttribute { }
|
||||
|
||||
#endif
|
124
Assets/Plugins/GameDesigner/Component/Core/NetworkBehaviour.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
using global::System;
|
||||
using Net.Share;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 网络行为基础组件
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(1000)]
|
||||
public abstract class NetworkBehaviour : MonoBehaviour
|
||||
{
|
||||
public NetworkObject netObj;
|
||||
[Tooltip("网络组件的ID,当FPS游戏时,自己身上只有一双手和枪,而其他客户端要显示完整模型时,用到另外的预制体,就会出现组件获取不一致问题,所以这里提供了网络组件ID,即可解决此问题")]
|
||||
[SerializeField] private int netComponentID = -1;
|
||||
/// <summary>
|
||||
/// 网络组件id, 此组件是netobj的第几个组件
|
||||
/// </summary>
|
||||
public int NetComponentID
|
||||
{
|
||||
get { return netComponentID > 10 ? -1 : netComponentID; }
|
||||
set
|
||||
{
|
||||
if (value > 10)
|
||||
throw new Exception("组件最多不能超过10个");
|
||||
netComponentID = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 这个物体是本机生成的?
|
||||
/// true:这个物体是从你本机实例化后, 同步给其他客户端的, 其他客户端的IsLocal为false
|
||||
/// false:这个物体是其他客户端实例化后,同步到本机客户端上, IsLocal为false
|
||||
/// </summary>
|
||||
public bool IsLocal => netObj.isLocal;
|
||||
private bool isInit;
|
||||
private bool isEnabled;
|
||||
public virtual void Start()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
private void OnValidate()
|
||||
{
|
||||
if (TryGetComponent(out netObj))
|
||||
return;
|
||||
netObj = gameObject.GetComponentInParent<NetworkObject>(true); //此处需要加上参数true, 否则做成预制体时会找不到父组件
|
||||
if (netObj == null)
|
||||
netObj = gameObject.AddComponent<NetworkObject>();
|
||||
}
|
||||
public void Init(Operation opt = default)
|
||||
{
|
||||
if (isInit)
|
||||
return;
|
||||
isInit = true;
|
||||
netObj = GetComponentInParent<NetworkObject>();
|
||||
if (NetComponentID == -1)
|
||||
{
|
||||
NetComponentID = netObj.networkBehaviours.Count;
|
||||
netObj.networkBehaviours.Add(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (netObj.networkBehaviours.Count <= NetComponentID)
|
||||
netObj.networkBehaviours.Add(null);
|
||||
if (netObj.networkBehaviours[NetComponentID] != null)
|
||||
throw new Exception($"索引有冲突!打开预制体设置{this}组件的NetComponentID值为唯一ID!");
|
||||
netObj.networkBehaviours[NetComponentID] = this;
|
||||
}
|
||||
netObj.InitSyncVar(this);
|
||||
if (IsLocal)
|
||||
OnNetworkObjectInit(netObj.Identity);
|
||||
else
|
||||
OnNetworkObjectCreate(opt);
|
||||
}
|
||||
/// <summary>
|
||||
/// 当网络物体被初始化, 只有本机实例化的物体才会被调用
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
public virtual void OnNetworkObjectInit(int identity) { }
|
||||
/// <summary>
|
||||
/// 当网络物体被创建后调用, 只有其他客户端发送创建信息给本机后才会被调用
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
public virtual void OnNetworkObjectCreate(Operation opt) { }
|
||||
/// <summary>
|
||||
/// 当网络操作到达后应当开发者进行处理
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
public virtual void OnNetworkOperationHandler(Operation opt) { }
|
||||
/// <summary>
|
||||
/// 当属性自动同步检查
|
||||
/// </summary>
|
||||
public virtual void OnPropertyAutoCheck() { }
|
||||
/// <summary>
|
||||
/// 检查组件是否启用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool CheckEnabled() { return isEnabled; }
|
||||
public virtual void OnEnable()
|
||||
{
|
||||
isEnabled = true;
|
||||
}
|
||||
public virtual void OnDisable()
|
||||
{
|
||||
isEnabled = false;
|
||||
}
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
netObj.RemoveSyncVar(this);
|
||||
var nbs = netObj.networkBehaviours;
|
||||
for (int i = 0; i < nbs.Count; i++)
|
||||
{
|
||||
var nb = nbs[i];
|
||||
nb.NetComponentID = i;
|
||||
if (nb == this)
|
||||
{
|
||||
nbs.RemoveAt(i);
|
||||
if (i >= 0) i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
299
Assets/Plugins/GameDesigner/Component/Core/NetworkManager.cs
Normal file
@@ -0,0 +1,299 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using Net.Client;
|
||||
using Net.Event;
|
||||
using Net.Share;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Net;
|
||||
using System;
|
||||
using Net.Helper;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
namespace Net.Component
|
||||
{
|
||||
[Serializable]
|
||||
public class ClientGourp
|
||||
{
|
||||
public string name;
|
||||
public ClientBase _client;
|
||||
public TransportProtocol protocol = TransportProtocol.Tcp;
|
||||
public string ip = "127.0.0.1";
|
||||
public int port = 9543;
|
||||
#if UNITY_EDITOR
|
||||
public bool localTest;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#endif
|
||||
public bool debugRpc = true;
|
||||
public bool authorize;
|
||||
public bool startConnect = true;
|
||||
public bool md5CRC;
|
||||
public bool singleThread;
|
||||
public int reconnectCount = 10;
|
||||
public int reconnectInterval = 2000;
|
||||
public byte heartLimit = 5;
|
||||
public int heartInterval = 1000;
|
||||
[Header("<22><><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
|
||||
public SerializeAdapterType type;
|
||||
public bool isEncrypt = false;//<2F><><EFBFBD>ݼ<EFBFBD><DDBC><EFBFBD>?
|
||||
public int password = 758426581;
|
||||
|
||||
public ClientBase Client
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_client != null)
|
||||
return _client;
|
||||
var typeName = $"Net.Client.{protocol}Client";
|
||||
var type = AssemblyHelper.GetType(typeName);
|
||||
if (type == null)
|
||||
throw new Exception($"<22>뵼<EFBFBD><EBB5BC>:{protocol}Э<><D0AD>!!!");
|
||||
_client = Activator.CreateInstance(type, new object[] { true }) as ClientBase;
|
||||
_client.host = ip;
|
||||
_client.port = port;
|
||||
_client.LogRpc = debugRpc;
|
||||
_client.MD5CRC = md5CRC;
|
||||
_client.IsMultiThread = !singleThread;
|
||||
_client.ReconnectCount = reconnectCount;
|
||||
_client.ReconnectInterval = reconnectInterval;
|
||||
_client.SetHeartTime(heartLimit, heartInterval);
|
||||
return _client;
|
||||
}
|
||||
set { _client = value; }
|
||||
}
|
||||
|
||||
public UniTask<bool> Connect()
|
||||
{
|
||||
_client = Client;
|
||||
var ips = Dns.GetHostAddresses(ip);
|
||||
if (ips.Length > 0)
|
||||
_client.host = ips[RandomHelper.Range(0, ips.Length)].ToString();
|
||||
else
|
||||
_client.host = ip;
|
||||
#if UNITY_EDITOR
|
||||
if (localTest) _client.host = "127.0.0.1";
|
||||
#endif
|
||||
_client.port = port;
|
||||
switch (type)
|
||||
{
|
||||
case SerializeAdapterType.Default:
|
||||
break;
|
||||
case SerializeAdapterType.PB_JSON_FAST:
|
||||
_client.AddAdapter(new Adapter.SerializeFastAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
case SerializeAdapterType.Binary:
|
||||
_client.AddAdapter(new Adapter.SerializeAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
case SerializeAdapterType.Binary2:
|
||||
_client.AddAdapter(new Adapter.SerializeAdapter2() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
case SerializeAdapterType.Binary3:
|
||||
_client.AddAdapter(new Adapter.SerializeAdapter3() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
}
|
||||
return _client.Connect(result =>
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
_client.Send(new byte[1]);//<2F><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ֽ<EFBFBD>:<3A><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>OnUnClientRequest<73><74><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>˺ŵ<CBBA>¼, <20><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public UniTask<bool> Connect(string ip, int port)
|
||||
{
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
return Connect();
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkManager : SingleCase<NetworkManager>
|
||||
{
|
||||
public LogMode logMode = LogMode.Default;
|
||||
public bool dontDestroyOnLoad = true;
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
[NonReorderable]
|
||||
#endif
|
||||
public List<ClientGourp> clients = new List<ClientGourp>();
|
||||
|
||||
public ClientBase this[int index]
|
||||
{
|
||||
get { return clients[index].Client; }
|
||||
set { clients[index].Client = value; }
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
if (dontDestroyOnLoad) DontDestroyOnLoad(gameObject);
|
||||
Application.runInBackground = true;
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
switch (logMode)
|
||||
{
|
||||
case LogMode.Default:
|
||||
NDebug.BindLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||
break;
|
||||
case LogMode.LogAll:
|
||||
NDebug.BindLogAll(Debug.Log);
|
||||
break;
|
||||
case LogMode.LogAndWarning:
|
||||
NDebug.BindLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||
break;
|
||||
case LogMode.WarnAndError:
|
||||
NDebug.BindLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyError:
|
||||
NDebug.BindLogAll(null, null, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyWarnAndError:
|
||||
NDebug.BindLogAll(null, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
}
|
||||
foreach (var client in clients)
|
||||
{
|
||||
if (client.startConnect)
|
||||
client.Connect();
|
||||
}
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
for (int i = 0; i < clients.Count; i++)
|
||||
{
|
||||
if (clients[i]._client == null)
|
||||
continue;
|
||||
clients[i]._client.NetworkTick();
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
for (int i = 0; i < clients.Count; i++)
|
||||
{
|
||||
if (clients[i]._client == null)
|
||||
continue;
|
||||
clients[i]._client.Close();
|
||||
}
|
||||
switch (logMode)
|
||||
{
|
||||
case LogMode.Default:
|
||||
NDebug.RemoveLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||
break;
|
||||
case LogMode.LogAll:
|
||||
NDebug.RemoveLogAll(Debug.Log);
|
||||
break;
|
||||
case LogMode.LogAndWarning:
|
||||
NDebug.RemoveLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||
break;
|
||||
case LogMode.WarnAndError:
|
||||
NDebug.RemoveLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyError:
|
||||
NDebug.RemoveLogAll(null, null, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyWarnAndError:
|
||||
NDebug.RemoveLogAll(null, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void BindNetworkAll(INetworkHandle handle)
|
||||
{
|
||||
foreach (var item in I.clients)
|
||||
{
|
||||
item.Client.BindNetworkHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>rpc, Ҳ<><D2B2><EFBFBD><EFBFBD>1<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public static void AddRpcOne(object target)
|
||||
{
|
||||
I.clients[0].Client.AddRpc(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>, Ҳ<><D2B2><EFBFBD><EFBFBD>2<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public static void AddRpcTwo(object target)
|
||||
{
|
||||
I.clients[1].Client.AddRpc(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>rpc, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>0<EFBFBD><30>Ϊȫ<CEAA><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="clientIndex"></param>
|
||||
/// <param name="target"></param>
|
||||
public static void AddRpc(int clientIndex, object target)
|
||||
{
|
||||
if (clientIndex < 0)
|
||||
foreach (var item in I.clients)
|
||||
item.Client.AddRpc(target);
|
||||
else I.clients[clientIndex].Client.AddRpc(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>rpc, Ҳ<><D2B2><EFBFBD><EFBFBD>1<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public static void RemoveRpcOne(object target)
|
||||
{
|
||||
I.clients[0].Client.RemoveRpc(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>rpc, Ҳ<><D2B2><EFBFBD><EFBFBD>2<EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public static void RemoveRpcTwo(object target)
|
||||
{
|
||||
var i = Instance;
|
||||
if (i == null)
|
||||
return;
|
||||
i.clients[1].Client.RemoveRpc(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20>Ƴ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀͻ<C4BF><CDBB><EFBFBD>rpc, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>0<EFBFBD><30>Ϊȫ<CEAA><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="clientIndex"></param>
|
||||
/// <param name="target"></param>
|
||||
public static void RemoveRpc(int clientIndex, object target)
|
||||
{
|
||||
var i = Instance;
|
||||
if (i == null)
|
||||
return;
|
||||
if (clientIndex < 0)
|
||||
foreach (var item in i.clients)
|
||||
item.Client.RemoveRpc(target);
|
||||
else i.clients[clientIndex].Client.RemoveRpc(target);
|
||||
}
|
||||
|
||||
public static void Close(bool v1, int v2)
|
||||
{
|
||||
foreach (var item in I.clients)
|
||||
{
|
||||
item.Client.Close(v1, v2);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CallUnity(Action ptr)
|
||||
{
|
||||
I.clients[0].Client.WorkerQueue.Enqueue(ptr);
|
||||
}
|
||||
|
||||
public static void DispatcherRpc(ushort hash, params object[] parms)
|
||||
{
|
||||
I.clients[1].Client.DispatchRpc(hash, parms);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
269
Assets/Plugins/GameDesigner/Component/Core/NetworkObject.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
using global::System.Collections.Generic;
|
||||
using Net.Client;
|
||||
using Net.Component;
|
||||
using Net.Helper;
|
||||
using Net.Share;
|
||||
using Net.System;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 网络物体标识组件
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
[DefaultExecutionOrder(1000)]
|
||||
public class NetworkObject : MonoBehaviour
|
||||
{
|
||||
internal static int IDENTITY { get; private set; } = -1;
|
||||
internal static int IDENTITY_MAX { get; private set; }
|
||||
internal static Queue<int> IDENTITY_POOL = new Queue<int>();
|
||||
public static int Capacity { get; private set; }
|
||||
public static bool IsInitIdentity => IDENTITY != -1;
|
||||
private int m_identity = -1;
|
||||
[Tooltip("自定义唯一标识, 当值不为0后,可以不通过NetworkSceneManager的registerObjects去设置, 直接放在设计的场景里面, 不需要做成预制体")]
|
||||
[SerializeField] private int identity;//可以设置的id
|
||||
[Tooltip("注册的网络物体索引, registerObjectIndex要对应NetworkSceneManager的registerObjects数组索引, 如果设置了自定义唯一标识, 则此字段无效!")]
|
||||
public int registerObjectIndex;
|
||||
[SerializeField] internal bool isLocal = true;
|
||||
internal List<NetworkBehaviour> networkBehaviours = new List<NetworkBehaviour>();
|
||||
internal MyDictionary<ushort, SyncVarInfo> syncVarInfos = new MyDictionary<ushort, SyncVarInfo>();
|
||||
private int syncVarID = 1;
|
||||
[Tooltip("是否初始化? 如果不想让Identity在Start被自动分配ID, 则可以设置此字段为true")]
|
||||
[SerializeField] internal bool isInit;
|
||||
public bool IsDispose { get; internal set; }
|
||||
/// <summary>
|
||||
/// 此物体是否是本机实例化?
|
||||
/// </summary>
|
||||
public bool IsLocal { get => isLocal; set => isLocal = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 每个网络对象的唯一标识
|
||||
/// </summary>
|
||||
public int Identity { get => m_identity; set => m_identity = value; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否初始化
|
||||
/// </summary>
|
||||
public bool IsInitialize { get => isInit; set => isInit = value; }
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
public void ReInit()
|
||||
{
|
||||
isInit = false;
|
||||
Init();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
if (isInit)
|
||||
return;
|
||||
isInit = true;
|
||||
if (IDENTITY == -1 & identity == 0)//全局netobj
|
||||
{
|
||||
Debug.LogError("网络标识未初始化,请调用NetworkObject.Init(5000);初始化");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
var sm = NetworkSceneManager.I;
|
||||
if (sm == null)
|
||||
{
|
||||
Debug.Log("没有找到NetworkSceneManager组件!NetworkIdentity组件无效!");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
if (!isLocal | m_identity > 0)
|
||||
{
|
||||
goto J1;
|
||||
}
|
||||
if (identity > 0)
|
||||
{
|
||||
m_identity = identity;
|
||||
goto J1;
|
||||
}
|
||||
if (IDENTITY_POOL.Count > 0)
|
||||
{
|
||||
m_identity = IDENTITY_POOL.Dequeue();
|
||||
goto J1;
|
||||
}
|
||||
if (IDENTITY < IDENTITY_MAX)
|
||||
{
|
||||
m_identity = IDENTITY++;
|
||||
goto J1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("网络标识已用完! 如果有需要请加大网络标识数量NetworkObject.Init(10000);");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
J1:
|
||||
if (!sm.identitys.TryAdd(m_identity, this, out var oldNetObj))
|
||||
{
|
||||
if (oldNetObj == this | oldNetObj == null)
|
||||
return;
|
||||
oldNetObj.m_identity = -1;
|
||||
Debug.Log($"uid:{m_identity}发生了两次实例化! 本地的实例化和网络同步下来的identity冲突");
|
||||
Destroy(oldNetObj.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void InitAll(Operation opt = default)
|
||||
{
|
||||
Init();
|
||||
var nbs = GetComponentsInChildren<NetworkBehaviour>();
|
||||
foreach (var np in nbs)
|
||||
{
|
||||
np.Init(opt);
|
||||
}
|
||||
}
|
||||
internal void InitSyncVar(object target)
|
||||
{
|
||||
ClientBase.Instance.AddRpcHandle(target, false, (info) =>
|
||||
{
|
||||
info.id = (ushort)syncVarID++;
|
||||
syncVarInfos.Add(info.id, info);
|
||||
if (!isLocal)
|
||||
{
|
||||
ClientBase.Instance.AddOperation(new Operation(NetCmd.SyncVarGet, m_identity)
|
||||
{
|
||||
index = registerObjectIndex,
|
||||
index1 = info.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
internal void CheckSyncVar()
|
||||
{
|
||||
if (syncVarInfos.Count == 0)
|
||||
return;
|
||||
var buffer = SyncVarHelper.CheckSyncVar(isLocal, syncVarInfos);
|
||||
if (buffer != null)
|
||||
SyncVarSend(buffer);
|
||||
}
|
||||
|
||||
private void SyncVarSend(byte[] buffer)
|
||||
{
|
||||
ClientBase.Instance.AddOperation(new Operation(NetCmd.SyncVarNetObj, m_identity)
|
||||
{
|
||||
uid = ClientBase.Instance.UID,
|
||||
index = registerObjectIndex,
|
||||
buffer = buffer
|
||||
});
|
||||
}
|
||||
|
||||
internal void SyncVarHandler(Operation opt)
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
SyncVarHelper.SyncVarHandler(syncVarInfos, opt.buffer);
|
||||
}
|
||||
|
||||
internal void RemoveSyncVar(NetworkBehaviour target)
|
||||
{
|
||||
SyncVarHelper.RemoveSyncVar(syncVarInfos, target);
|
||||
}
|
||||
|
||||
internal void PropertyAutoCheckHandler()
|
||||
{
|
||||
for (int i = 0; i < networkBehaviours.Count; i++)
|
||||
{
|
||||
var networkBehaviour = networkBehaviours[i];
|
||||
if (!networkBehaviour.CheckEnabled())
|
||||
continue;
|
||||
networkBehaviour.OnPropertyAutoCheck();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
if (IsDispose)
|
||||
return;
|
||||
IsDispose = true;
|
||||
if (m_identity == -1)
|
||||
return;
|
||||
var sm = NetworkSceneManager.Instance;
|
||||
if (sm == null)
|
||||
return;
|
||||
if (!isLocal | m_identity < 10000)//0-10000是场景可用标识
|
||||
{
|
||||
sm.waitDestroyList.Add(new WaitDestroy(m_identity, false, Time.time + 1f));
|
||||
return;
|
||||
}
|
||||
sm.waitDestroyList.Add(new WaitDestroy(m_identity, true, Time.time + 1f));
|
||||
if (ClientBase.Instance == null)
|
||||
return;
|
||||
if (!ClientBase.Instance.Connected)
|
||||
return;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.Destroy, m_identity));
|
||||
}
|
||||
|
||||
internal static void PushIdentity(int identity)
|
||||
{
|
||||
if (IDENTITY == -1)
|
||||
return;
|
||||
IDENTITY_POOL.Enqueue(identity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化网络唯一标识
|
||||
/// </summary>
|
||||
/// <param name="capacity">一个客户端可以用的唯一标识容量</param>
|
||||
public static void Init(int capacity = 5000)
|
||||
{
|
||||
//要实时可初始化,要不然每次切换场景都无法初始化id,或者切换账号后uid变了,就得不到真正的identity值了
|
||||
Capacity = capacity;
|
||||
//0-10000是公共id,10000-15000是玩家uid,也就是同时在线5000个玩家,每个玩家占用一个id,15000-20000是uid=10000的网络物体id,
|
||||
//每个玩家可以实例化5000个网络物体,并且id都是唯一的,如果超出则报错
|
||||
IDENTITY = 10000 + ((ClientBase.Instance.UID + 1 - 10000) * capacity);
|
||||
IDENTITY_MAX = IDENTITY + capacity;
|
||||
IDENTITY_POOL.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放初始化的identity
|
||||
/// </summary>
|
||||
public static void UnInit()
|
||||
{
|
||||
IDENTITY = -1;
|
||||
IDENTITY_MAX = 0;
|
||||
Capacity = 0;
|
||||
IDENTITY_POOL.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取玩家id的偏移量, 此方法算出来每个玩家可实例化多少个网络对象
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetUserIdOffset(int uid)
|
||||
{
|
||||
//0-10000是公共id,10000-15000是玩家uid,也就是同时在线5000个玩家,每个玩家占用一个id,15000-20000是uid=10000的网络物体id,
|
||||
//每个玩家可以实例化5000个网络物体,并且id都是唯一的,如果超出则报错
|
||||
return 10000 + ((uid + 1 - 10000) * Capacity);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
var networkBehaviours = gameObject.GetComponentsInChildren<NetworkBehaviour>(true);
|
||||
for (int i = 0; i < networkBehaviours.Length; i++)
|
||||
{
|
||||
var networkBehaviour = networkBehaviours[i];
|
||||
if (networkBehaviour.NetComponentID == -1)
|
||||
{
|
||||
networkBehaviour.NetComponentID = i;
|
||||
UnityEditor.EditorUtility.SetDirty(networkBehaviour);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,75 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Net.Component;
|
||||
using System.Collections.Generic;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
[Serializable]
|
||||
public class ObjectRecord
|
||||
{
|
||||
public int ID;
|
||||
public Object obj;
|
||||
public string path;//编辑器模式使用,任何物体都可以同步
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网络资源同步
|
||||
/// 此类主要用于同步字段为unity的组件或者基于UnityEngine.Objec的类型
|
||||
/// 在编辑器模式下是任何物体都可以同步的, 注意: 在编译项目后, 只能同步在Resources文件夹下的预制体或物体
|
||||
/// </summary>
|
||||
public class NetworkResources : SingleCase<NetworkResources>
|
||||
{
|
||||
public ObjectRecord[] objectRecords;
|
||||
public Dictionary<Object, ObjectRecord> dic = new Dictionary<Object, ObjectRecord>();
|
||||
public Dictionary<string, ObjectRecord> dic1 = new Dictionary<string, ObjectRecord>();
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
var objects = Resources.LoadAll<Object>("");
|
||||
objectRecords = new ObjectRecord[objects.Length];
|
||||
for (int i = 0; i < objects.Length; i++)
|
||||
{
|
||||
objectRecords[i] = new ObjectRecord() { ID = i, obj = objects[i] };
|
||||
dic.Add(objects[i], objectRecords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryGetValue(Object obj, out ObjectRecord objectRecord)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!dic.TryGetValue(obj, out objectRecord))
|
||||
{
|
||||
var path = UnityEditor.AssetDatabase.GetAssetPath(obj);
|
||||
objectRecord = new ObjectRecord() { ID = dic.Count, obj = obj, path = path };
|
||||
dic.Add(obj, objectRecord);
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return dic.TryGetValue(obj, out objectRecord);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal T GetObject<T>(int index, string path) where T : Object
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if(string.IsNullOrEmpty(path))
|
||||
return null;
|
||||
if (!dic1.TryGetValue(path, out ObjectRecord objectRecord))
|
||||
{
|
||||
var obj = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(T));
|
||||
objectRecord = new ObjectRecord() { ID = dic1.Count, obj = obj, path = path };
|
||||
dic1.Add(path, objectRecord);
|
||||
}
|
||||
return (T)objectRecord.obj;
|
||||
#else
|
||||
return (T)objectRecords[index].obj;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,323 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
using global::System;
|
||||
using global::System.Collections.Generic;
|
||||
using Net.Client;
|
||||
using Net.Component;
|
||||
using Net.Share;
|
||||
using Net.System;
|
||||
using UnityEngine;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
[Serializable]
|
||||
public class WaitDestroy
|
||||
{
|
||||
public int identity;
|
||||
public bool isPush;
|
||||
public float time;
|
||||
|
||||
public WaitDestroy(int identity, bool isPush, float time)
|
||||
{
|
||||
this.identity = identity;
|
||||
this.isPush = isPush;
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
|
||||
[DefaultExecutionOrder(1)]
|
||||
public class NetworkSceneManager : SingleCase<NetworkSceneManager>
|
||||
{
|
||||
public List<NetworkObject> registerObjects = new List<NetworkObject>();
|
||||
[HideInInspector]
|
||||
public MyDictionary<int, NetworkObject> identitys = new MyDictionary<int, NetworkObject>();
|
||||
[Tooltip("如果onExitDelectAll=true 当客户端退出游戏,客户端所创建的所有网络物体也将随之被删除? onExitDelectAll=false只删除玩家物体")]
|
||||
public bool onExitDelectAll = true;
|
||||
internal List<WaitDestroy> waitDestroyList = new List<WaitDestroy>();
|
||||
protected ClientBase client; //当多场景时, 退出战斗场景, 回主场景时, 先进入主场景再卸载战斗场景, 而ClientBase.Instance被赋值到其他多连接客户端对象上就会出现OnDestry时没有正确移除OnOperationSync事件
|
||||
protected Queue<Action> waitNetworkIdentityQueue = new Queue<Action>();
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
_ = WaitConnecting();
|
||||
if (NetworkTime.Instance == null)
|
||||
gameObject.AddComponent<NetworkTime>();
|
||||
}
|
||||
|
||||
public virtual async UniTaskVoid WaitConnecting()
|
||||
{
|
||||
var outTime = DateTime.Now.AddSeconds(10);
|
||||
while (DateTime.Now < outTime)
|
||||
{
|
||||
if (ClientBase.Instance == null)
|
||||
await UniTask.Yield();
|
||||
else if (!ClientBase.Instance.Connected)
|
||||
await UniTask.Yield();
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (DateTime.Now > outTime)
|
||||
{
|
||||
Debug.Log("连接超时!");
|
||||
return;
|
||||
}
|
||||
OnConnected();
|
||||
client = ClientBase.Instance;
|
||||
client.OnOperationSync += OperationSync;
|
||||
while (waitNetworkIdentityQueue.Count > 0)
|
||||
waitNetworkIdentityQueue.Dequeue()?.Invoke();
|
||||
}
|
||||
|
||||
public virtual void OnConnected()
|
||||
{
|
||||
NetworkObject.Init(5000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待网络标识初始化, 当标识初始化完成调用onInitComplete委托
|
||||
/// </summary>
|
||||
/// <param name="onInitComplete"></param>
|
||||
public virtual void WaitNetworkIdentityInit(Action onInitComplete)
|
||||
{
|
||||
if (NetworkObject.IsInitIdentity)
|
||||
onInitComplete?.Invoke();
|
||||
else
|
||||
waitNetworkIdentityQueue.Enqueue(onInitComplete);
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
if (NetworkTime.CanSent)
|
||||
{
|
||||
for (int i = 0; i < identitys.count; i++)
|
||||
{
|
||||
if (identitys.entries[i].hashCode == -1)
|
||||
continue;
|
||||
var identity = identitys.entries[i].value;
|
||||
if (identity == null)
|
||||
continue;
|
||||
if (!identity.enabled)
|
||||
continue;
|
||||
if (identity.IsDispose)
|
||||
continue;
|
||||
identity.CheckSyncVar();
|
||||
identity.PropertyAutoCheckHandler();
|
||||
}
|
||||
}
|
||||
WaitDestroy waitDestroy;
|
||||
for (int i = 0; i < waitDestroyList.Count; i++)
|
||||
{
|
||||
waitDestroy = waitDestroyList[i];
|
||||
if (Time.time >= waitDestroy.time)
|
||||
{
|
||||
RemoveIdentity(waitDestroy.identity);
|
||||
waitDestroyList.RemoveAt(i);
|
||||
if (!waitDestroy.isPush)
|
||||
continue;
|
||||
NetworkObject.PushIdentity(waitDestroy.identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OperationSync(OperationList list)
|
||||
{
|
||||
foreach (var opt in list.operations)
|
||||
OnNetworkOperSync(opt);
|
||||
}
|
||||
|
||||
private void OnNetworkOperSync(Operation opt)
|
||||
{
|
||||
switch (opt.cmd)
|
||||
{
|
||||
case Command.Transform:
|
||||
OnBuildOrTransformSync(opt);
|
||||
break;
|
||||
case Command.BuildComponent:
|
||||
OnBuildOrTransformSync(opt);
|
||||
break;
|
||||
case Command.Destroy:
|
||||
OnNetworkObjectDestroy(opt);
|
||||
break;
|
||||
case Command.OnPlayerExit:
|
||||
OnPlayerExit(opt);
|
||||
break;
|
||||
case NetCmd.SyncVarNetObj:
|
||||
OnSyncVarHandler(opt);
|
||||
break;
|
||||
case NetCmd.SyncVarGet:
|
||||
SyncVarGetHandler(opt);
|
||||
break;
|
||||
case NetCmd.CallRpc:
|
||||
var data = client.OnDeserializeRPC(opt.buffer, 0, opt.buffer.Length);
|
||||
if(!string.IsNullOrEmpty(data.name))
|
||||
client.DispatchRpc(data.name, data.pars);
|
||||
else if(data.hash != 0)
|
||||
client.DispatchRpc(data.hash, data.pars);
|
||||
break;
|
||||
default:
|
||||
OnOtherOperator(opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当检查网络标识物体,如果不存在就会实例化 --- 在这里用到了<see cref="Operation.identity"/>作为网络物体标识, <see cref="Operation.index"/>作为要实例化<see cref="registerObjects"/>的物体索引
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <returns></returns>
|
||||
public virtual NetworkObject OnCheckIdentity(Operation opt)
|
||||
{
|
||||
if (!identitys.TryGetValue(opt.identity, out NetworkObject identity))
|
||||
{
|
||||
if (opt.index >= registerObjects.Count)
|
||||
return null;
|
||||
identity = Instantiate(registerObjects[opt.index]);
|
||||
identity.Identity = opt.identity;
|
||||
identity.isLocal = false;
|
||||
identity.isInit = true;
|
||||
identity.InitAll(opt);
|
||||
identitys.TryAdd(opt.identity, identity);
|
||||
OnNetworkObjectCreate(opt, identity);
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当BuildComponent指令或Transform指令同步时调用
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
public virtual void OnBuildOrTransformSync(Operation opt)
|
||||
{
|
||||
var identity = OnCheckIdentity(opt);
|
||||
if (identity == null)
|
||||
return;
|
||||
if (identity.IsDispose)
|
||||
return;
|
||||
var nb = identity.networkBehaviours[opt.index1];
|
||||
nb.OnNetworkOperationHandler(opt);
|
||||
}
|
||||
|
||||
public virtual void OnSyncVarHandler(Operation opt)
|
||||
{
|
||||
var identity = OnCheckIdentity(opt);
|
||||
if (identity == null)
|
||||
return;
|
||||
if (identity.IsDispose)
|
||||
return;
|
||||
identity.SyncVarHandler(opt);
|
||||
}
|
||||
|
||||
public virtual void SyncVarGetHandler(Operation opt)
|
||||
{
|
||||
var identity = OnCheckIdentity(opt);
|
||||
if (identity == null)
|
||||
return;
|
||||
if (identity.IsDispose)
|
||||
return;
|
||||
if (!identity.isLocal)
|
||||
return;
|
||||
identity.syncVarInfos[(ushort)opt.index1].SetDefaultValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当其他网络物体被删除(入口1)
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
public virtual void OnNetworkObjectDestroy(Operation opt)
|
||||
{
|
||||
if (identitys.TryGetValue(opt.identity, out NetworkObject identity))
|
||||
{
|
||||
OnPlayerDestroy(identity, false);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnPlayerExit(Operation opt)
|
||||
{
|
||||
if (identitys.TryGetValue(opt.identity, out NetworkObject identity))//删除退出游戏的玩家游戏物体
|
||||
OnPlayerDestroy(identity, true);
|
||||
if (onExitDelectAll)//删除此玩家所创建的所有游戏物体
|
||||
{
|
||||
var uid = NetworkObject.GetUserIdOffset(opt.identity);
|
||||
var count = uid + NetworkObject.Capacity;
|
||||
foreach (var item in identitys)
|
||||
if (item.Key >= uid & item.Key < count)
|
||||
OnPlayerDestroy(item.Value, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerDestroy(NetworkObject identity, bool isPlayer)
|
||||
{
|
||||
if (identity == null)
|
||||
return;
|
||||
if (identity.IsDispose)
|
||||
return;
|
||||
if(isPlayer)
|
||||
OnOtherExit(identity);
|
||||
OnOtherDestroy(identity);
|
||||
}
|
||||
|
||||
public void RemoveIdentity(int identity)
|
||||
{
|
||||
identitys.Remove(identity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当其他网络物体被创建(实例化)
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
/// <param name="identity"></param>
|
||||
public virtual void OnNetworkObjectCreate(Operation opt, NetworkObject identity)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当其他网络物体被删除(入口2)
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
public virtual void OnOtherDestroy(NetworkObject identity)
|
||||
{
|
||||
Destroy(identity.gameObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当其他玩家网络物体退出(删除)
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
public virtual void OnOtherExit(NetworkObject identity)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当其他操作指令调用
|
||||
/// </summary>
|
||||
/// <param name="opt"></param>
|
||||
public virtual void OnOtherOperator(Operation opt)
|
||||
{
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
ExitSceneHandler();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当退出场景时有些网络物体是不应该被销毁的
|
||||
/// </summary>
|
||||
public void ExitSceneHandler()
|
||||
{
|
||||
foreach (var identity in identitys)
|
||||
{
|
||||
identity.Value.Identity = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
NetworkObject.UnInit();//每次离开战斗场景都要清除初始化identity
|
||||
if (client == null)
|
||||
return;
|
||||
client.OnOperationSync -= OperationSync;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,14 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using UnityEngine;
|
||||
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络Transform同步组件基类
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(1000)]
|
||||
public class NetworkTransform : NetworkTransformBase
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,202 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
using Net.Client;
|
||||
using Net.Component;
|
||||
using Net.Share;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public enum SyncMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 自身同步, 只有自身才能控制, 同步给其他客户端, 其他客户端无法控制这个物体的移动
|
||||
/// </summary>
|
||||
Local,
|
||||
/// <summary>
|
||||
/// 完全控制, 所有客户端都可以移动这个物体, 并且其他客户端都会被同步
|
||||
/// 同步条件是哪个先移动这个物体会有<see cref="NetworkTransformBase.interval"/>秒完全控制,
|
||||
/// 其他客户端无法控制,如果先移动的客户端一直移动这个物体,则其他客户端无法移动,只有先移动的客户端停止操作,下个客户端才能同步这个物体
|
||||
/// </summary>
|
||||
Control,
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// </summary>
|
||||
Authorize,
|
||||
/// <summary>
|
||||
/// 自身同步在其他客户端显示的状态
|
||||
/// </summary>
|
||||
Synchronized,
|
||||
/// <summary>
|
||||
/// 完全控制在其他客户端显示的状态
|
||||
/// </summary>
|
||||
SynchronizedAll,
|
||||
/// <summary>
|
||||
/// 空同步
|
||||
/// </summary>
|
||||
None,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网络Transform同步组件基类
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(1000)]
|
||||
public abstract class NetworkTransformBase : NetworkBehaviour
|
||||
{
|
||||
protected Net.Vector3 position;
|
||||
protected Net.Quaternion rotation;
|
||||
protected Net.Vector3 localScale;
|
||||
public SyncMode syncMode = SyncMode.Local;
|
||||
public bool syncPosition = true;
|
||||
public bool syncRotation = true;
|
||||
public bool syncScale = false;
|
||||
[HideInInspector] public SyncMode currMode = SyncMode.None;
|
||||
internal float sendTime;
|
||||
public float interval = 0.5f;
|
||||
protected Net.Vector3 netPosition;
|
||||
protected Net.Quaternion netRotation;
|
||||
protected Net.Vector3 netLocalScale;
|
||||
public float rate = 30f;//网络帧率, 一秒30次
|
||||
public float lerpSpeed = 0.3f;
|
||||
public bool fixedSync = true;
|
||||
public float fixedSendTime = 1f;//固定发送时间
|
||||
internal float fixedTime;
|
||||
|
||||
// Update is called once per frame
|
||||
public virtual void Update()
|
||||
{
|
||||
if (netObj.Identity == -1 | currMode == SyncMode.None)
|
||||
return;
|
||||
if (currMode == SyncMode.Synchronized)
|
||||
{
|
||||
SyncTransform();
|
||||
}
|
||||
else if (Time.time > sendTime)
|
||||
{
|
||||
Check();
|
||||
sendTime = Time.time + (1f / rate);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Check()
|
||||
{
|
||||
if (transform.position != position | transform.rotation != rotation | transform.localScale != localScale | (Time.time > fixedTime & fixedSync))
|
||||
{
|
||||
position = transform.position;
|
||||
rotation = transform.rotation;
|
||||
localScale = transform.localScale;
|
||||
fixedTime = Time.time + fixedSendTime;
|
||||
StartSyncTransformState();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void StartSyncTransformState()
|
||||
{
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.Transform, netObj.Identity, syncScale ? localScale : Net.Vector3.zero, syncPosition ? position : Net.Vector3.zero, syncRotation ? rotation : Net.Quaternion.zero)
|
||||
{
|
||||
cmd1 = (byte)currMode,
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
|
||||
public virtual void SyncTransform()
|
||||
{
|
||||
if (syncPosition)
|
||||
transform.position = Vector3.Lerp(transform.position, netPosition, lerpSpeed);
|
||||
if (syncRotation)
|
||||
if (netRotation != Net.Quaternion.identity)
|
||||
transform.rotation = Quaternion.Lerp(transform.rotation, netRotation, lerpSpeed);
|
||||
if (syncScale)
|
||||
transform.localScale = netLocalScale;
|
||||
}
|
||||
|
||||
public virtual void SyncControlTransform()
|
||||
{
|
||||
if (syncPosition)
|
||||
{
|
||||
position = netPosition;//位置要归位,要不然就会发送数据
|
||||
transform.position = netPosition;
|
||||
}
|
||||
if (syncRotation)
|
||||
{
|
||||
rotation = netRotation;
|
||||
transform.rotation = netRotation;
|
||||
}
|
||||
if (syncScale)
|
||||
{
|
||||
localScale = netLocalScale;
|
||||
transform.localScale = netLocalScale;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkObjectInit(int identity)
|
||||
{
|
||||
currMode = syncMode;
|
||||
}
|
||||
|
||||
public override void OnNetworkObjectCreate(Operation opt)
|
||||
{
|
||||
if (opt.cmd == Command.Transform)
|
||||
{
|
||||
var mode1 = (SyncMode)opt.cmd1;
|
||||
if (mode1 == SyncMode.Control | mode1 == SyncMode.SynchronizedAll)
|
||||
currMode = SyncMode.SynchronizedAll;
|
||||
else
|
||||
currMode = SyncMode.Synchronized;
|
||||
}
|
||||
netPosition = opt.position;
|
||||
netRotation = opt.rotation;
|
||||
netLocalScale = opt.direction;
|
||||
SyncControlTransform();
|
||||
}
|
||||
|
||||
public override void OnNetworkOperationHandler(Operation opt)
|
||||
{
|
||||
if (ClientBase.Instance.UID == opt.uid)
|
||||
return;
|
||||
sendTime = Time.time + interval;
|
||||
netPosition = opt.position;
|
||||
netRotation = opt.rotation;
|
||||
netLocalScale = opt.direction;
|
||||
if (currMode == SyncMode.SynchronizedAll | currMode == SyncMode.Control)
|
||||
SyncControlTransform();
|
||||
else if (currMode == SyncMode.None)
|
||||
{
|
||||
var mode1 = (SyncMode)opt.cmd1;
|
||||
if (mode1 == SyncMode.Control | mode1 == SyncMode.SynchronizedAll)
|
||||
currMode = SyncMode.SynchronizedAll;
|
||||
else
|
||||
currMode = SyncMode.Synchronized;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetNetworkPosition(Net.Vector3 position)
|
||||
{
|
||||
netPosition = position;
|
||||
}
|
||||
|
||||
public void SetNetworkRotation(Net.Quaternion rotation)
|
||||
{
|
||||
netRotation = rotation;
|
||||
}
|
||||
|
||||
public void SetNetworkPositionAndRotation(Net.Vector3 position, Net.Quaternion rotation)
|
||||
{
|
||||
netPosition = position;
|
||||
netRotation = rotation;
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
if (ClientBase.Instance == null)
|
||||
return;
|
||||
//如果在退出游戏或者退出场景后不让物体被销毁,则需要查找netobj组件设置Identity等于-1,或者查找此组件设置currMode等于None,或者在点击处理的时候调用ClientBase.Instance.Close方法
|
||||
if ((currMode == SyncMode.SynchronizedAll | currMode == SyncMode.Control) & netObj.Identity != -1 & ClientBase.Instance.Connected)
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.Destroy, netObj.Identity));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,159 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.UnityComponent
|
||||
{
|
||||
using Net.Component;
|
||||
using Net.Share;
|
||||
using global::System;
|
||||
using UnityEngine;
|
||||
using Net.Client;
|
||||
|
||||
/// <summary>
|
||||
/// 网络Transform同步组件基类
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(1000)]
|
||||
public class NetworkTransformMulti : NetworkTransformBase
|
||||
{
|
||||
public ChildTransform[] childs;
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
for (int i = 0; i < childs.Length; i++)
|
||||
{
|
||||
childs[i].Init(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (netObj.Identity == -1 | currMode == SyncMode.None)
|
||||
return;
|
||||
if (currMode == SyncMode.Synchronized)
|
||||
{
|
||||
SyncTransform();
|
||||
for (int i = 0; i < childs.Length; i++)
|
||||
{
|
||||
childs[i].SyncTransform();
|
||||
}
|
||||
}
|
||||
else if (Time.time > sendTime)
|
||||
{
|
||||
Check();
|
||||
for (int i = 0; i < childs.Length; i++)
|
||||
{
|
||||
childs[i].Check(netObj.Identity, netObj.registerObjectIndex, NetComponentID);
|
||||
}
|
||||
sendTime = Time.time + (1f / rate);
|
||||
}
|
||||
}
|
||||
|
||||
public override void StartSyncTransformState()
|
||||
{
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.Transform, netObj.Identity, syncScale ? localScale : Net.Vector3.zero, syncPosition ? position : Net.Vector3.zero, syncRotation ? rotation : Net.Quaternion.zero)
|
||||
{
|
||||
cmd1 = (byte)currMode,
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnNetworkOperationHandler(Operation opt)
|
||||
{
|
||||
if (ClientBase.Instance.UID == opt.uid)
|
||||
return;
|
||||
sendTime = Time.time + interval;
|
||||
if (opt.index2 == 0)
|
||||
{
|
||||
netPosition = opt.position;
|
||||
netRotation = opt.rotation;
|
||||
netLocalScale = opt.direction;
|
||||
if (currMode == SyncMode.SynchronizedAll | currMode == SyncMode.Control)
|
||||
SyncControlTransform();
|
||||
else if (currMode == SyncMode.None)
|
||||
{
|
||||
var mode1 = (SyncMode)opt.cmd1;
|
||||
if (mode1 == SyncMode.Control | mode1 == SyncMode.SynchronizedAll)
|
||||
currMode = SyncMode.SynchronizedAll;
|
||||
else
|
||||
currMode = SyncMode.Synchronized;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var child = childs[opt.index2 - 1];
|
||||
child.netPosition = opt.position;
|
||||
child.netRotation = opt.rotation;
|
||||
child.netLocalScale = opt.direction;
|
||||
if (child.mode == SyncMode.SynchronizedAll | child.mode == SyncMode.Control)
|
||||
child.SyncControlTransform();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ChildTransform
|
||||
{
|
||||
public string name;
|
||||
public Transform transform;
|
||||
internal Net.Vector3 position;
|
||||
internal Net.Quaternion rotation;
|
||||
internal Net.Vector3 localScale;
|
||||
public SyncMode mode = SyncMode.Control;
|
||||
public bool syncPosition = true;
|
||||
public bool syncRotation = true;
|
||||
public bool syncScale = false;
|
||||
public int identity = -1;//自身id
|
||||
internal Net.Vector3 netPosition;
|
||||
internal Net.Quaternion netRotation;
|
||||
internal Net.Vector3 netLocalScale;
|
||||
|
||||
internal void Init(int identity)
|
||||
{
|
||||
this.identity = identity;
|
||||
position = transform.localPosition;
|
||||
rotation = transform.localRotation;
|
||||
localScale = transform.localScale;
|
||||
}
|
||||
|
||||
internal void Check(int identity, int index, int netIndex)
|
||||
{
|
||||
if (transform.localPosition != position | transform.localRotation != rotation | transform.localScale != localScale)
|
||||
{
|
||||
position = transform.localPosition;
|
||||
rotation = transform.localRotation;
|
||||
localScale = transform.localScale;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.Transform, identity, syncScale ? localScale : Net.Vector3.zero, syncPosition ? position : Net.Vector3.zero, syncRotation ? rotation : Net.Quaternion.zero)
|
||||
{
|
||||
cmd1 = (byte)mode,
|
||||
uid = ClientBase.Instance.UID,
|
||||
index = index,
|
||||
index1 = netIndex,
|
||||
index2 = this.identity
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void SyncTransform()
|
||||
{
|
||||
if (syncPosition)
|
||||
transform.localPosition = Vector3.Lerp(transform.localPosition, netPosition, 0.3f);
|
||||
if (syncRotation)
|
||||
if (netRotation != Net.Quaternion.identity)
|
||||
transform.localRotation = Quaternion.Lerp(transform.localRotation, netRotation, 0.3f);
|
||||
if (syncScale)
|
||||
transform.localScale = netLocalScale;
|
||||
}
|
||||
|
||||
public void SyncControlTransform()
|
||||
{
|
||||
if (syncPosition)
|
||||
transform.localPosition = netPosition;
|
||||
if (syncRotation)
|
||||
transform.localRotation = netRotation;
|
||||
if (syncScale)
|
||||
transform.localScale = netLocalScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,514 @@
|
||||
#if UNITY_EDITOR
|
||||
using Net.Helper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using static Fast2BuildTools2;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
public class BuildComponentTools : EditorWindow
|
||||
{
|
||||
private Data data = new Data();
|
||||
private Object component;
|
||||
private Object oldComponent;
|
||||
private FoldoutData foldout;
|
||||
private Vector2 scrollPosition1;
|
||||
|
||||
[MenuItem("GameDesigner/Network/BuildComponentTools")]
|
||||
public static void Init()
|
||||
{
|
||||
GetWindow<BuildComponentTools>("BuildComponentTools", true);
|
||||
}
|
||||
private void OnEnable()
|
||||
{
|
||||
LoadData();
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
SaveData();
|
||||
}
|
||||
void OnGUI()
|
||||
{
|
||||
component = EditorGUILayout.ObjectField("组件", component, typeof(Object), true);
|
||||
if (component != oldComponent)
|
||||
{
|
||||
oldComponent = component;
|
||||
if (component != null)
|
||||
{
|
||||
var type = component.GetType();
|
||||
//var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
|
||||
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
||||
var fields1 = new List<FieldData>();
|
||||
//foreach (var item in fields)
|
||||
//{
|
||||
// fields1.Add(new FieldData() { name = item.Name, serialize = true });
|
||||
//}
|
||||
foreach (var item in properties)
|
||||
{
|
||||
if (!item.CanRead | !item.CanWrite)
|
||||
continue;
|
||||
if (item.GetIndexParameters().Length > 0)
|
||||
continue;
|
||||
if (item.GetCustomAttribute<ObsoleteAttribute>() != null)
|
||||
continue;
|
||||
var ptype = item.PropertyType;
|
||||
var code = Type.GetTypeCode(ptype);
|
||||
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) & ptype != typeof(Object) & !ptype.IsSubclassOf(typeof(Object)))
|
||||
continue;
|
||||
fields1.Add(new FieldData() { name = item.Name });
|
||||
}
|
||||
for (int i = 0; i < methods.Length; i++)
|
||||
{
|
||||
var met = methods[i];
|
||||
if (met.MethodImplementationFlags == MethodImplAttributes.InternalCall | met.Name.Contains("get_") | met.Name.Contains("set_") |
|
||||
met.GetCustomAttribute<ObsoleteAttribute>() != null | met.IsGenericMethod)
|
||||
continue;
|
||||
var pars = met.GetParameters();
|
||||
bool not = false;
|
||||
foreach (var item in pars)
|
||||
{
|
||||
var ptype = item.ParameterType;
|
||||
var code = Type.GetTypeCode(ptype);
|
||||
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) //& ptype != typeof(Object) & !ptype.IsSubclassOf(typeof(Object))
|
||||
)
|
||||
{
|
||||
not = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
continue;
|
||||
fields1.Add(new FieldData() { name = met.ToString() });
|
||||
}
|
||||
foldout = new FoldoutData() { name = type.Name, fields = fields1, foldout = true };
|
||||
}
|
||||
}
|
||||
if (foldout != null)
|
||||
{
|
||||
scrollPosition1 = GUILayout.BeginScrollView(scrollPosition1, false, true);
|
||||
var rect = EditorGUILayout.GetControlRect();
|
||||
foldout.foldout = EditorGUI.Foldout(rect, foldout.foldout, foldout.name + "", true);
|
||||
if (foldout.foldout)
|
||||
{
|
||||
EditorGUI.indentLevel = 1;
|
||||
for (int i = 0; i < foldout.fields.Count; i++)
|
||||
{
|
||||
var rect1 = EditorGUILayout.GetControlRect();
|
||||
rect1.x += 20;
|
||||
var width = rect1.width;
|
||||
rect1.width = 180;
|
||||
foldout.fields[i].select = GUI.Toolbar(rect1, foldout.fields[i].select, new string[] { "同步调用", "本地调用", "忽略" });
|
||||
rect1.x += 200;
|
||||
rect1.width = width - 200;
|
||||
GUIStyle titleStyle2 = new GUIStyle();
|
||||
switch (foldout.fields[i].select)
|
||||
{
|
||||
case 0:
|
||||
titleStyle2.normal.textColor = Color.white;
|
||||
break;
|
||||
case 1:
|
||||
titleStyle2.normal.textColor = Color.green;
|
||||
break;
|
||||
case 2:
|
||||
titleStyle2.normal.textColor = Color.red;
|
||||
break;
|
||||
}
|
||||
GUI.Label(rect1, foldout.fields[i].name, titleStyle2);
|
||||
|
||||
}
|
||||
EditorGUI.indentLevel = 0;
|
||||
}
|
||||
if (rect.Contains(Event.current.mousePosition) & Event.current.button == 1)
|
||||
{
|
||||
GenericMenu menu = new GenericMenu();
|
||||
menu.AddItem(new GUIContent("全部同步调用勾上"), false, () =>
|
||||
{
|
||||
foldout.fields.ForEach(item => item.select = 0);
|
||||
});
|
||||
menu.AddItem(new GUIContent("全部本地调用勾上"), false, () =>
|
||||
{
|
||||
foldout.fields.ForEach(item => item.select = 1);
|
||||
});
|
||||
menu.AddItem(new GUIContent("智能本地调用勾上"), false, () =>
|
||||
{
|
||||
foldout.fields.ForEach(item => {
|
||||
if (item.name.Contains("Get") | item.name.Contains("Is"))
|
||||
item.select = 1;
|
||||
});
|
||||
});
|
||||
menu.AddItem(new GUIContent("全部取消"), false, () =>
|
||||
{
|
||||
foldout.fields.ForEach(item => item.select = 2);
|
||||
});
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
GUILayout.EndScrollView();
|
||||
}
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField("保存路径:", data.savePath);
|
||||
if (GUILayout.Button("选择路径", GUILayout.Width(100)))
|
||||
{
|
||||
data.savePath = EditorUtility.OpenFolderPanel("保存路径", "", "");
|
||||
SaveData();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
if (GUILayout.Button("生成同步组件脚本", GUILayout.Height(40)))
|
||||
{
|
||||
if (string.IsNullOrEmpty(data.savePath))
|
||||
{
|
||||
EditorUtility.DisplayDialog("提示", "请选择生成脚本路径!", "确定");
|
||||
return;
|
||||
}
|
||||
if (component == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("提示", "请选择unity组件!", "确定");
|
||||
return;
|
||||
}
|
||||
var type = component.GetType();
|
||||
var str = BuildNew(type, foldout.fields.ConvertAll((item) => item.select == 2 ? item.name : ""), foldout.fields.ConvertAll((item) => item.select == 1 ? item.name : ""));
|
||||
File.WriteAllText(data.savePath + $"//Network{type.Name}.cs", str.ToString());
|
||||
Debug.Log("生成脚本成功!");
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
static StringBuilder BuildNew(Type type, List<string> ignores, List<string> immediatelys)
|
||||
{
|
||||
var templateCode = @"#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using Net.Client;
|
||||
using Net.Share;
|
||||
using Net.Component;
|
||||
using Net.UnityComponent;
|
||||
using UnityEngine;
|
||||
using Net.System;
|
||||
using static Net.Serialize.NetConvertFast2;
|
||||
|
||||
namespace BuildComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// {TypeName1}同步组件, 此代码由BuildComponentTools工具生成, 如果同步发生相互影响的字段或属性, 请自行检查处理一下!
|
||||
/// </summary>
|
||||
[RequireComponent(typeof({TypeName}))]
|
||||
public class Network{TypeName1} : NetworkBehaviour
|
||||
{
|
||||
private {TypeName} self;
|
||||
public bool autoCheck;
|
||||
private object[] fields;
|
||||
private int[] eventsId;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
self = GetComponent<{TypeName}>();
|
||||
[Split]
|
||||
fields = new object[{FieldSize}];
|
||||
eventsId = new int[{FieldSize}];
|
||||
[Split]
|
||||
fields[{FieldIndex}] = self.{TypeFieldName};
|
||||
[Split]
|
||||
}
|
||||
|
||||
[Split]
|
||||
public {PropertyType} {TypeFieldName}
|
||||
{
|
||||
get
|
||||
{
|
||||
return self.{TypeFieldName};
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals({FieldName}))
|
||||
return;
|
||||
{FieldName} = value;
|
||||
self.{TypeFieldName} = value;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = Index,
|
||||
index2 = {FieldIndex},
|
||||
buffer = SerializeObject(value).ToArray(true),
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
}
|
||||
[Split]
|
||||
public override void OnPropertyAutoCheck()
|
||||
{
|
||||
if (!autoCheck)
|
||||
return;
|
||||
[Split]
|
||||
{TypeFieldName} = {TypeFieldName};
|
||||
[Split]
|
||||
}
|
||||
[Split]
|
||||
public void {FuncName}({ParsString} bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if ({Condition} !always) return;
|
||||
{SetPars}
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { {Params} } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = Index,
|
||||
index2 = {FieldIndex},
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[{EIDIndex}]);
|
||||
eventsId[{EIDIndex}] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
{FuncName}({Params} true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
[Split]
|
||||
public {ReturnType} {FuncName}({ParsString})
|
||||
{
|
||||
{Return}self.{FuncName}({Params});
|
||||
}
|
||||
[Split]
|
||||
public override void OnNetworkOperationHandler(Operation opt)
|
||||
{
|
||||
switch (opt.index2)
|
||||
{
|
||||
[Split]
|
||||
case {FieldIndex1}:
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
var {TypeFieldName} = DeserializeObject<{FieldType1}>(new Segment(opt.buffer, false));
|
||||
{FieldName} = {TypeFieldName};
|
||||
self.{TypeFieldName} = {TypeFieldName};
|
||||
}
|
||||
break;
|
||||
[Split]
|
||||
case {FieldIndex1}:
|
||||
{
|
||||
self.{FuncName}();
|
||||
}
|
||||
break;
|
||||
[Split]
|
||||
case {FieldIndex1}:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
{SetPars}
|
||||
self.{FuncName}({Params});
|
||||
}
|
||||
break;
|
||||
[Split]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
" + @"#endif";
|
||||
|
||||
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
|
||||
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringBuilder sb1 = new StringBuilder();
|
||||
StringBuilder sb2 = new StringBuilder();
|
||||
StringBuilder sb3 = new StringBuilder();
|
||||
StringBuilder sb4 = new StringBuilder();
|
||||
StringBuilder sb5 = new StringBuilder();
|
||||
|
||||
templateCode = templateCode.Replace("{TypeName1}", $"{type.Name}");
|
||||
templateCode = templateCode.Replace("{TypeName}", $"{type.FullName}");
|
||||
|
||||
var blockCodes = templateCode.Split(new string[] { "[Split]" }, 0);
|
||||
blockCodes[0] = blockCodes[0].Remove(blockCodes[0].Length - 2, 2);
|
||||
sb.Append(blockCodes[0]);
|
||||
|
||||
int parNum = 0;
|
||||
for (int i = 0; i < properties.Length; i++)
|
||||
{
|
||||
var item = properties[i];
|
||||
if (ignores.Contains(item.Name))
|
||||
continue;
|
||||
if (!item.CanRead | !item.CanWrite | item.GetCustomAttribute<ObsoleteAttribute>() != null)
|
||||
continue;
|
||||
var ptype = item.PropertyType;
|
||||
var code = Type.GetTypeCode(ptype);
|
||||
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) & ptype != typeof(UnityEngine.Object) & !ptype.IsSubclassOf(typeof(UnityEngine.Object))
|
||||
)
|
||||
continue;
|
||||
parNum++;
|
||||
var blockCode = blockCodes[2];
|
||||
blockCode = blockCode.Replace("{FieldIndex}", $"{parNum}");
|
||||
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb1.Append(blockCode);
|
||||
|
||||
blockCode = blockCodes[4];
|
||||
blockCode = blockCode.Replace("{PropertyType}", $"{item.PropertyType.FullName}");
|
||||
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||
blockCode = blockCode.Replace("{FieldName}", $"fields[{parNum}]");
|
||||
blockCode = blockCode.Replace("{FieldIndex}", $"{parNum}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb2.Append(blockCode);
|
||||
|
||||
blockCode = blockCodes[6];
|
||||
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb3.Append(blockCode);
|
||||
|
||||
blockCode = blockCodes[11];
|
||||
blockCode = blockCode.Replace("{FieldIndex1}", $"{parNum}");
|
||||
blockCode = blockCode.Replace("{FieldName}", $"fields[{parNum}]");
|
||||
blockCode = blockCode.Replace("{FieldType1}", $"{item.PropertyType.FullName}");
|
||||
blockCode = blockCode.Replace("{TypeFieldName}", $"{item.Name}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb5.Append(blockCode);
|
||||
}
|
||||
for (int i = 0; i < methods.Length; i++)
|
||||
{
|
||||
var met = methods[i];
|
||||
var metName = met.ToString();
|
||||
if (ignores.Contains(metName))
|
||||
continue;
|
||||
if (met.MethodImplementationFlags == MethodImplAttributes.InternalCall | met.Name.Contains("get_") | met.Name.Contains("set_") |
|
||||
met.GetCustomAttribute<ObsoleteAttribute>() != null | met.IsGenericMethod)
|
||||
continue;
|
||||
var pars = met.GetParameters();
|
||||
bool not = false;
|
||||
foreach (var item in pars)
|
||||
{
|
||||
var ptype = item.ParameterType;
|
||||
var code = Type.GetTypeCode(ptype);
|
||||
if (code == TypeCode.Object & ptype != typeof(Vector2) & ptype != typeof(Vector3) & ptype != typeof(Vector4) &
|
||||
ptype != typeof(Rect) & ptype != typeof(Quaternion) & ptype != typeof(Color)
|
||||
& ptype != typeof(Color32) & ptype != typeof(Net.Vector2) & ptype != typeof(Net.Vector3)
|
||||
& ptype != typeof(Net.Vector4) & ptype != typeof(Net.Rect) & ptype != typeof(Net.Quaternion)
|
||||
& ptype != typeof(Net.Color) & ptype != typeof(Net.Color32) //& ptype != typeof(Object) & !ptype.IsSubclassOf(typeof(Object))
|
||||
)
|
||||
{
|
||||
not = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not)
|
||||
continue;
|
||||
string blockCode;
|
||||
var parsStr = "";
|
||||
var conditionStr = "";
|
||||
var setValueStr = "";
|
||||
var paramsStr = "";
|
||||
var setValueStr1 = "";
|
||||
parNum++;
|
||||
var metIndex = parNum;
|
||||
foreach (var item in pars)
|
||||
{
|
||||
parNum++;
|
||||
parsStr += $"{item.ParameterType.FullName} {item.Name},";
|
||||
conditionStr += $"{item.Name}.Equals(fields[{parNum}]) & ";
|
||||
setValueStr += $"fields[{parNum}] = {item.Name};\r\n\t\t\t";
|
||||
paramsStr += $"{item.Name},";
|
||||
setValueStr1 += $"var {item.Name} = ({item.ParameterType.FullName})(fields[{parNum}] = data.Obj);\r\n\t\t\t\t\t\t";
|
||||
}
|
||||
if (setValueStr.Length > 0)
|
||||
setValueStr = setValueStr.Remove(setValueStr.Length - 5, 5);
|
||||
if (setValueStr1.Length > 0)
|
||||
setValueStr1 = setValueStr1.Remove(setValueStr1.Length - 8, 8);
|
||||
|
||||
if (immediatelys.Contains(metName))
|
||||
{
|
||||
parsStr = parsStr.TrimEnd(',');
|
||||
paramsStr = paramsStr.TrimEnd(',');
|
||||
blockCode = blockCodes[9];
|
||||
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||
blockCode = blockCode.Replace("{ParsString}", $"{parsStr}");
|
||||
blockCode = blockCode.Replace("{ReturnType}", $"{(met.ReturnType == typeof(void) ? "void" : met.ReturnType.FullName)}");
|
||||
blockCode = blockCode.Replace("{Return}", $"{(met.ReturnType == typeof(void) ? "" : "return ")}");
|
||||
blockCode = blockCode.Replace("{Params}", $"{paramsStr}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb4.Append(blockCode);
|
||||
parNum = metIndex - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
blockCode = blockCodes[8];
|
||||
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||
blockCode = blockCode.Replace("{ParsString}", $"{parsStr}");
|
||||
blockCode = blockCode.Replace("{Condition}", $"{conditionStr}");
|
||||
blockCode = blockCode.Replace("{SetPars}", $"{setValueStr}");
|
||||
blockCode = blockCode.Replace("{Params}", $"{paramsStr}");
|
||||
blockCode = blockCode.Replace("{FieldIndex}", $"{metIndex}");
|
||||
|
||||
blockCode = blockCode.Replace("{EIDIndex}", $"{metIndex}");
|
||||
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb4.Append(blockCode);
|
||||
|
||||
if (pars.Length == 0)
|
||||
{
|
||||
blockCode = blockCodes[12];
|
||||
blockCode = blockCode.Replace("{FieldIndex1}", $"{metIndex}");
|
||||
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb5.Append(blockCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
paramsStr = paramsStr.TrimEnd(',');
|
||||
blockCode = blockCodes[13];
|
||||
blockCode = blockCode.Replace("{FieldIndex1}", $"{metIndex}");
|
||||
blockCode = blockCode.Replace("{FuncName}", $"{met.Name}");
|
||||
blockCode = blockCode.Replace("{Params}", $"{paramsStr}");
|
||||
blockCode = blockCode.Replace("{SetPars}", $"{setValueStr1}");
|
||||
blockCode = blockCode.Remove(blockCode.Length - 2, 2);
|
||||
sb5.Append(blockCode);
|
||||
}
|
||||
}
|
||||
|
||||
var blockCodeX = blockCodes[1];
|
||||
blockCodeX = blockCodeX.Replace("{FieldSize}", $"{parNum}");
|
||||
blockCodeX = blockCodeX.Remove(blockCodeX.Length - 2, 2);
|
||||
sb.Append(blockCodeX);
|
||||
sb.Append(sb1.ToString());
|
||||
sb.Append(blockCodes[3]);
|
||||
|
||||
sb.Append(sb2.ToString());
|
||||
|
||||
sb.Append(blockCodes[5]);
|
||||
sb.Append(sb3.ToString());
|
||||
sb.Append(blockCodes[7]);
|
||||
|
||||
sb.Append(sb4.ToString());
|
||||
|
||||
sb.Append(blockCodes[10]);
|
||||
sb.Append(sb5.ToString());
|
||||
sb.Append(blockCodes[14]);
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
void LoadData()
|
||||
{
|
||||
data = PersistHelper.Deserialize<Data>("networkComponentBuild.json");
|
||||
}
|
||||
void SaveData()
|
||||
{
|
||||
PersistHelper.Serialize(data, "networkComponentBuild.json");
|
||||
}
|
||||
internal class Data
|
||||
{
|
||||
public string savePath, savePath1;
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
/// <summary>
|
||||
/// 只显示不能修改属性绘制
|
||||
/// </summary>
|
||||
[CustomPropertyDrawer(typeof(DisplayOnly))]
|
||||
public class ReadOnlyDrawer : PropertyDrawer
|
||||
{
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUI.GetPropertyHeight(property, label, true);
|
||||
}
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
GUI.enabled = false;
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///绘制多选属性
|
||||
///</summary>
|
||||
[CustomPropertyDrawer(typeof(EnumFlags))]
|
||||
public class EnumFlagsDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
property.intValue = EditorGUI.MaskField(position, label, property.intValue, property.enumNames);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,25 @@
|
||||
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||
using Net.UnityComponent;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(NetworkObject))]
|
||||
[CanEditMultipleObjects]
|
||||
public class NetworkObjectEdit : Editor
|
||||
{
|
||||
private NetworkObject no;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
no = target as NetworkObject;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.LabelField("Network Identity", no.Identity.ToString());
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,31 @@
|
||||
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||
using Net.UnityComponent;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(NetworkSceneManager))]
|
||||
[CanEditMultipleObjects]
|
||||
public class NetworkSceneManagerEdit : Editor
|
||||
{
|
||||
private NetworkSceneManager nt;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
nt = target as NetworkSceneManager;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
if (GUILayout.Button("<22><><EFBFBD><EFBFBD>registerObjectIndex"))
|
||||
{
|
||||
for (int i = 0; i < nt.registerObjects.Count; i++)
|
||||
{
|
||||
nt.registerObjects[i].registerObjectIndex = i;
|
||||
EditorUtility.SetDirty(nt.registerObjects[i]);
|
||||
}
|
||||
EditorUtility.SetDirty(nt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,25 @@
|
||||
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||
using Net.UnityComponent;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(NetworkTransform))]
|
||||
[CanEditMultipleObjects]
|
||||
public class NetworkTransformEdit : Editor
|
||||
{
|
||||
private NetworkTransform nt;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
nt = target as NetworkTransform;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.LabelField("mode", nt.currMode.ToString());
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,49 @@
|
||||
#if (UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL) && UNITY_EDITOR
|
||||
using Net.UnityComponent;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
[CustomEditor(typeof(NetworkTransformMulti))]
|
||||
[CanEditMultipleObjects]
|
||||
public class NetworkTransformMultiEdit : Editor
|
||||
{
|
||||
private NetworkTransformMulti nt;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
nt = target as NetworkTransformMulti;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.LabelField("mode", nt.currMode.ToString());
|
||||
GUI.enabled = true;
|
||||
if (GUILayout.Button("更新子物体"))
|
||||
{
|
||||
var childs1 = nt.transform.GetComponentsInChildren<Transform>();
|
||||
var list = new List<ChildTransform>();
|
||||
foreach (var child in childs1)
|
||||
{
|
||||
if (child == nt.transform)
|
||||
continue;
|
||||
if (!child.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
list.Add(new ChildTransform()
|
||||
{
|
||||
name = child.name,
|
||||
transform = child,
|
||||
mode = nt.syncMode,
|
||||
syncPosition = nt.syncPosition,
|
||||
syncRotation = nt.syncRotation,
|
||||
syncScale = nt.syncScale,
|
||||
});
|
||||
}
|
||||
nt.childs = list.ToArray();
|
||||
EditorUtility.SetDirty(nt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1,648 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using Net.Client;
|
||||
using Net.Share;
|
||||
using Net.Component;
|
||||
using Net.UnityComponent;
|
||||
using UnityEngine;
|
||||
using Net.System;
|
||||
using static Net.Serialize.NetConvertFast2;
|
||||
|
||||
namespace BuildComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Animation同步组件, 此代码由BuildComponentTools工具生成, 如果同步发生相互影响的字段或属性, 请自行检查处理一下!
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(UnityEngine.Animation))]
|
||||
public class NetworkAnimation : NetworkBehaviour
|
||||
{
|
||||
private UnityEngine.Animation self;
|
||||
public bool autoCheck;
|
||||
private object[] fields;
|
||||
private int[] eventsId;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
self = GetComponent<UnityEngine.Animation>();
|
||||
fields = new object[40];
|
||||
eventsId = new int[40];
|
||||
fields[1] = self.clip;
|
||||
fields[2] = self.playAutomatically;
|
||||
fields[3] = self.wrapMode;
|
||||
fields[4] = self.animatePhysics;
|
||||
fields[5] = self.cullingType;
|
||||
}
|
||||
|
||||
public UnityEngine.AnimationClip clip
|
||||
{
|
||||
get
|
||||
{
|
||||
return self.clip;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals(fields[1]))
|
||||
return;
|
||||
fields[1] = value;
|
||||
self.clip = value;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 1,
|
||||
buffer = SerializeObject(value).ToArray(true),
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
}
|
||||
public System.Boolean playAutomatically
|
||||
{
|
||||
get
|
||||
{
|
||||
return self.playAutomatically;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals(fields[2]))
|
||||
return;
|
||||
fields[2] = value;
|
||||
self.playAutomatically = value;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 2,
|
||||
buffer = SerializeObject(value).ToArray(true),
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
}
|
||||
public UnityEngine.WrapMode wrapMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return self.wrapMode;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals(fields[3]))
|
||||
return;
|
||||
fields[3] = value;
|
||||
self.wrapMode = value;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 3,
|
||||
buffer = SerializeObject(value).ToArray(true),
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
}
|
||||
public System.Boolean animatePhysics
|
||||
{
|
||||
get
|
||||
{
|
||||
return self.animatePhysics;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals(fields[4]))
|
||||
return;
|
||||
fields[4] = value;
|
||||
self.animatePhysics = value;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 4,
|
||||
buffer = SerializeObject(value).ToArray(true),
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
}
|
||||
public UnityEngine.AnimationCullingType cullingType
|
||||
{
|
||||
get
|
||||
{
|
||||
return self.cullingType;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Equals(fields[5]))
|
||||
return;
|
||||
fields[5] = value;
|
||||
self.cullingType = value;
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 5,
|
||||
buffer = SerializeObject(value).ToArray(true),
|
||||
uid = ClientBase.Instance.UID
|
||||
});
|
||||
}
|
||||
}
|
||||
public override void OnPropertyAutoCheck()
|
||||
{
|
||||
if (!autoCheck)
|
||||
return;
|
||||
|
||||
clip = clip;
|
||||
playAutomatically = playAutomatically;
|
||||
wrapMode = wrapMode;
|
||||
animatePhysics = animatePhysics;
|
||||
cullingType = cullingType;
|
||||
}
|
||||
|
||||
public void Stop(System.String name, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (name.Equals(fields[7]) & !always) return;
|
||||
fields[7] = name;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { name, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 6,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[6]);
|
||||
eventsId[6] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Stop(name, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void Rewind(System.String name, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (name.Equals(fields[9]) & !always) return;
|
||||
fields[9] = name;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { name, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 8,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[8]);
|
||||
eventsId[8] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Rewind(name, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void Play( bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if ( !always) return;
|
||||
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 10,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[10]);
|
||||
eventsId[10] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Play( true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void Play(UnityEngine.PlayMode mode, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (mode.Equals(fields[12]) & !always) return;
|
||||
fields[12] = mode;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { mode, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 11,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[11]);
|
||||
eventsId[11] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Play(mode, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void Play(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[14]) & !always) return;
|
||||
fields[14] = animation;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 13,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[13]);
|
||||
eventsId[13] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Play(animation, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void CrossFade(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[16]) & !always) return;
|
||||
fields[16] = animation;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 15,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[15]);
|
||||
eventsId[15] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
CrossFade(animation, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void CrossFade(System.String animation,System.Single fadeLength, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[18]) & fadeLength.Equals(fields[19]) & !always) return;
|
||||
fields[18] = animation;
|
||||
fields[19] = fadeLength;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,fadeLength, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 17,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[17]);
|
||||
eventsId[17] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
CrossFade(animation,fadeLength, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void Blend(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[21]) & !always) return;
|
||||
fields[21] = animation;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 20,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[20]);
|
||||
eventsId[20] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Blend(animation, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void Blend(System.String animation,System.Single targetWeight, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[23]) & targetWeight.Equals(fields[24]) & !always) return;
|
||||
fields[23] = animation;
|
||||
fields[24] = targetWeight;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,targetWeight, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 22,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[22]);
|
||||
eventsId[22] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
Blend(animation,targetWeight, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void CrossFadeQueued(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[26]) & !always) return;
|
||||
fields[26] = animation;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 25,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[25]);
|
||||
eventsId[25] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
CrossFadeQueued(animation, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void CrossFadeQueued(System.String animation,System.Single fadeLength, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[28]) & fadeLength.Equals(fields[29]) & !always) return;
|
||||
fields[28] = animation;
|
||||
fields[29] = fadeLength;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,fadeLength, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 27,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[27]);
|
||||
eventsId[27] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
CrossFadeQueued(animation,fadeLength, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void CrossFadeQueued(System.String animation,System.Single fadeLength,UnityEngine.QueueMode queue, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[31]) & fadeLength.Equals(fields[32]) & queue.Equals(fields[33]) & !always) return;
|
||||
fields[31] = animation;
|
||||
fields[32] = fadeLength;
|
||||
fields[33] = queue;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,fadeLength,queue, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 30,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[30]);
|
||||
eventsId[30] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
CrossFadeQueued(animation,fadeLength,queue, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void PlayQueued(System.String animation, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[35]) & !always) return;
|
||||
fields[35] = animation;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 34,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[34]);
|
||||
eventsId[34] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
PlayQueued(animation, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void PlayQueued(System.String animation,UnityEngine.QueueMode queue, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (animation.Equals(fields[37]) & queue.Equals(fields[38]) & !always) return;
|
||||
fields[37] = animation;
|
||||
fields[38] = queue;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { animation,queue, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 36,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[36]);
|
||||
eventsId[36] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
PlayQueued(animation,queue, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public void RemoveClip(System.String clipName, bool always = false, int executeNumber = 0, float time = 0)
|
||||
{
|
||||
if (clipName.Equals(fields[40]) & !always) return;
|
||||
fields[40] = clipName;
|
||||
var buffer = SerializeModel(new RPCModel() { pars = new object[] { clipName, } });
|
||||
ClientBase.Instance.AddOperation(new Operation(Command.BuildComponent, netObj.Identity)
|
||||
{
|
||||
index = netObj.registerObjectIndex,
|
||||
index1 = NetComponentID,
|
||||
index2 = 39,
|
||||
buffer = buffer
|
||||
});
|
||||
if (executeNumber > 0)
|
||||
{
|
||||
ThreadManager.Event.RemoveEvent(eventsId[39]);
|
||||
eventsId[39] = ThreadManager.Event.AddEvent(time, executeNumber, (obj)=> {
|
||||
RemoveClip(clipName, true, 0, 0);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
public System.Collections.IEnumerator GetEnumerator()
|
||||
{
|
||||
return self.GetEnumerator();
|
||||
}
|
||||
public UnityEngine.AnimationClip GetClip(System.String name)
|
||||
{
|
||||
return self.GetClip(name);
|
||||
}
|
||||
public override void OnNetworkOperationHandler(Operation opt)
|
||||
{
|
||||
switch (opt.index2)
|
||||
{
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
var clip = DeserializeObject<UnityEngine.AnimationClip>(new Segment(opt.buffer, false));
|
||||
fields[1] = clip;
|
||||
self.clip = clip;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
var playAutomatically = DeserializeObject<System.Boolean>(new Segment(opt.buffer, false));
|
||||
fields[2] = playAutomatically;
|
||||
self.playAutomatically = playAutomatically;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
var wrapMode = DeserializeObject<UnityEngine.WrapMode>(new Segment(opt.buffer, false));
|
||||
fields[3] = wrapMode;
|
||||
self.wrapMode = wrapMode;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
var animatePhysics = DeserializeObject<System.Boolean>(new Segment(opt.buffer, false));
|
||||
fields[4] = animatePhysics;
|
||||
self.animatePhysics = animatePhysics;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
if (opt.uid == ClientBase.Instance.UID)
|
||||
return;
|
||||
var cullingType = DeserializeObject<UnityEngine.AnimationCullingType>(new Segment(opt.buffer, false));
|
||||
fields[5] = cullingType;
|
||||
self.cullingType = cullingType;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var name = (System.String)(fields[7] = data.Obj);
|
||||
self.Stop(name);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var name = (System.String)(fields[9] = data.Obj);
|
||||
self.Rewind(name);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
{
|
||||
self.Play();
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var mode = (UnityEngine.PlayMode)(fields[12] = data.Obj);
|
||||
self.Play(mode);
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[14] = data.Obj);
|
||||
self.Play(animation);
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[16] = data.Obj);
|
||||
self.CrossFade(animation);
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[18] = data.Obj);
|
||||
var fadeLength = (System.Single)(fields[19] = data.Obj);
|
||||
self.CrossFade(animation,fadeLength);
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[21] = data.Obj);
|
||||
self.Blend(animation);
|
||||
}
|
||||
break;
|
||||
case 22:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[23] = data.Obj);
|
||||
var targetWeight = (System.Single)(fields[24] = data.Obj);
|
||||
self.Blend(animation,targetWeight);
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[26] = data.Obj);
|
||||
self.CrossFadeQueued(animation);
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[28] = data.Obj);
|
||||
var fadeLength = (System.Single)(fields[29] = data.Obj);
|
||||
self.CrossFadeQueued(animation,fadeLength);
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[31] = data.Obj);
|
||||
var fadeLength = (System.Single)(fields[32] = data.Obj);
|
||||
var queue = (UnityEngine.QueueMode)(fields[33] = data.Obj);
|
||||
self.CrossFadeQueued(animation,fadeLength,queue);
|
||||
}
|
||||
break;
|
||||
case 34:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[35] = data.Obj);
|
||||
self.PlayQueued(animation);
|
||||
}
|
||||
break;
|
||||
case 36:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var animation = (System.String)(fields[37] = data.Obj);
|
||||
var queue = (UnityEngine.QueueMode)(fields[38] = data.Obj);
|
||||
self.PlayQueued(animation,queue);
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
{
|
||||
var segment = new Segment(opt.buffer, false);
|
||||
var data = DeserializeModel(segment);
|
||||
var clipName = (System.String)(fields[40] = data.Obj);
|
||||
self.RemoveClip(clipName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
2288
Assets/Plugins/GameDesigner/Component/Generate/NetworkAnimator.cs
Normal file
360
Assets/Plugins/GameDesigner/Component/Manager/ClientManager.cs
Normal file
@@ -0,0 +1,360 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.Component
|
||||
{
|
||||
using Net.Client;
|
||||
using Net.Event;
|
||||
using Net.Share;
|
||||
using global::System;
|
||||
using global::System.Threading;
|
||||
using UnityEngine;
|
||||
using global::System.Net;
|
||||
using Net.Helper;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
public enum TransportProtocol
|
||||
{
|
||||
Tcp, Gcp, Udx, Kcp, Web
|
||||
}
|
||||
|
||||
public enum LogMode
|
||||
{
|
||||
None,
|
||||
/// <summary>
|
||||
/// 消息输出, 警告输出, 错误输出, 三种模式各自输出
|
||||
/// </summary>
|
||||
Default,
|
||||
/// <summary>
|
||||
/// 所有消息输出都以白色消息输出
|
||||
/// </summary>
|
||||
LogAll,
|
||||
/// <summary>
|
||||
/// 警告信息和消息一起输出为白色
|
||||
/// </summary>
|
||||
LogAndWarning,
|
||||
/// <summary>
|
||||
/// 警告和错误都输出为红色提示
|
||||
/// </summary>
|
||||
WarnAndError,
|
||||
/// <summary>
|
||||
/// 只输出错误日志
|
||||
/// </summary>
|
||||
OnlyError,
|
||||
/// <summary>
|
||||
/// 只输入警告和错误日志
|
||||
/// </summary>
|
||||
OnlyWarnAndError,
|
||||
}
|
||||
|
||||
[DefaultExecutionOrder(1)]//在NetworkTransform组件之前执行OnDestroy,控制NetworkTransform处于Control模式时退出游戏会同步删除所有网络物体
|
||||
public class ClientManager : SingleCase<ClientManager>, ISendHandle
|
||||
{
|
||||
private bool mainInstance;
|
||||
private ClientBase _client;
|
||||
public TransportProtocol protocol = TransportProtocol.Tcp;
|
||||
public string ip = "127.0.0.1";
|
||||
public int port = 9543;
|
||||
#if UNITY_EDITOR
|
||||
public bool localTest;
|
||||
#endif
|
||||
public LogMode logMode = LogMode.Default;
|
||||
public bool debugRpc = true;
|
||||
public bool authorize;
|
||||
public bool startConnect = true;
|
||||
public bool md5CRC;
|
||||
public int reconnectCount = 10;
|
||||
public int reconnectInterval = 2000;
|
||||
public byte heartLimit = 5;
|
||||
public int heartInterval = 1000;
|
||||
public bool dontDestroyOnLoad = true;
|
||||
|
||||
#pragma warning disable IDE1006 // 命名样式
|
||||
public ClientBase client
|
||||
#pragma warning restore IDE1006 // 命名样式
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_client == null)
|
||||
{
|
||||
var typeName = $"Net.Client.{protocol}Client";
|
||||
var type = AssemblyHelper.GetType(typeName);
|
||||
if (type == null)
|
||||
throw new Exception($"请导入:{protocol}协议!!!");
|
||||
_client = Activator.CreateInstance(type, new object[] { true }) as ClientBase;
|
||||
_client.host = ip;
|
||||
_client.port = port;
|
||||
_client.LogRpc = debugRpc;
|
||||
_client.MD5CRC = md5CRC;
|
||||
_client.ReconnectCount = reconnectCount;
|
||||
_client.ReconnectInterval = reconnectInterval;
|
||||
_client.SetHeartTime(heartLimit, heartInterval);
|
||||
}
|
||||
return _client;
|
||||
}
|
||||
set { _client = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端唯一标识
|
||||
/// </summary>
|
||||
public static string Identify { get { return Instance.client.Identify; } }
|
||||
/// <summary>
|
||||
/// 客户端唯一标识
|
||||
/// </summary>
|
||||
public static int UID { get { return Instance.client.UID; } }
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
mainInstance = true;
|
||||
if (dontDestroyOnLoad) DontDestroyOnLoad(gameObject);
|
||||
Application.runInBackground = true;
|
||||
}
|
||||
|
||||
// Use this for initialization
|
||||
void Start()
|
||||
{
|
||||
switch (logMode)
|
||||
{
|
||||
case LogMode.Default:
|
||||
NDebug.BindLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||
break;
|
||||
case LogMode.LogAll:
|
||||
NDebug.BindLogAll(Debug.Log);
|
||||
break;
|
||||
case LogMode.LogAndWarning:
|
||||
NDebug.BindLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||
break;
|
||||
case LogMode.WarnAndError:
|
||||
NDebug.BindLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyError:
|
||||
NDebug.BindLogAll(null, null, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyWarnAndError:
|
||||
NDebug.BindLogAll(null, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
}
|
||||
if (startConnect)
|
||||
Connect();
|
||||
}
|
||||
|
||||
public UniTask<bool> Connect()
|
||||
{
|
||||
_client = client;
|
||||
var ips = Dns.GetHostAddresses(ip);
|
||||
if (ips.Length > 0)
|
||||
_client.host = ips[RandomHelper.Range(0, ips.Length)].ToString();
|
||||
else
|
||||
_client.host = ip;
|
||||
#if UNITY_EDITOR
|
||||
if (localTest) _client.host = "127.0.0.1";
|
||||
#endif
|
||||
_client.port = port;
|
||||
_client.AddRpcHandle(this);
|
||||
return _client.Connect(result =>
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
_client.Send(new byte[1]);//发送一个字节:调用服务器的OnUnClientRequest方法, 如果不需要账号登录, 则会直接允许进入服务器
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (_client == null)
|
||||
return;
|
||||
_client.NetworkTick();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (!mainInstance)
|
||||
return;
|
||||
_client?.Close();
|
||||
switch (logMode)
|
||||
{
|
||||
case LogMode.Default:
|
||||
NDebug.RemoveLogAll(Debug.Log, Debug.LogWarning, Debug.LogError);
|
||||
break;
|
||||
case LogMode.LogAll:
|
||||
NDebug.RemoveLogAll(Debug.Log);
|
||||
break;
|
||||
case LogMode.LogAndWarning:
|
||||
NDebug.RemoveLogAll(Debug.Log, Debug.Log, Debug.LogError);
|
||||
break;
|
||||
case LogMode.WarnAndError:
|
||||
NDebug.RemoveLogAll(Debug.Log, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyError:
|
||||
NDebug.RemoveLogAll(null, null, Debug.LogError);
|
||||
break;
|
||||
case LogMode.OnlyWarnAndError:
|
||||
NDebug.RemoveLogAll(null, Debug.LogError, Debug.LogError);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发起场景同步操作, 在同一个场景的所有客户端都会收到该操作参数operation
|
||||
/// </summary>
|
||||
/// <param name="operation"></param>
|
||||
public static void AddOperation(Operation operation)
|
||||
{
|
||||
Instance.client.AddOperation(operation);
|
||||
}
|
||||
|
||||
public static void AddRpc(object target)
|
||||
{
|
||||
I.client.AddRpcHandle(target);
|
||||
}
|
||||
|
||||
public static void RemoveRpc(object target)
|
||||
{
|
||||
I.client.RemoveRpc(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断name是否是本地唯一id(本机玩家标识)
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsLocal(string name)
|
||||
{
|
||||
if (Instance == null)
|
||||
return false;
|
||||
return instance._client.Identify == name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断uid是否是本地唯一id(本机玩家标识)
|
||||
/// </summary>
|
||||
/// <param name="uid"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool IsLocal(int uid)
|
||||
{
|
||||
if (Instance == null)
|
||||
return false;
|
||||
return instance._client.UID == uid;
|
||||
}
|
||||
|
||||
public static void CallUnity(Action ptr)
|
||||
{
|
||||
I.client.WorkerQueue.Enqueue(ptr);
|
||||
}
|
||||
|
||||
#region 发送接口实现
|
||||
public void Send(byte[] buffer)
|
||||
{
|
||||
((ISendHandle)_client).Send(buffer);
|
||||
}
|
||||
|
||||
public void Send(byte cmd, byte[] buffer)
|
||||
{
|
||||
((ISendHandle)_client).Send(cmd, buffer);
|
||||
}
|
||||
|
||||
public void Send(string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(func, pars);
|
||||
}
|
||||
|
||||
public void Send(byte cmd, string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(cmd, func, pars);
|
||||
}
|
||||
|
||||
public void CallRpc(string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).CallRpc(func, pars);
|
||||
}
|
||||
|
||||
public void CallRpc(byte cmd, string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).CallRpc(cmd, func, pars);
|
||||
}
|
||||
|
||||
public void Request(string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Request(func, pars);
|
||||
}
|
||||
|
||||
public void Request(byte cmd, string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Request(cmd, func, pars);
|
||||
}
|
||||
|
||||
public void SendRT(string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(func, pars);
|
||||
}
|
||||
|
||||
public void SendRT(byte cmd, string func, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(cmd, func, pars);
|
||||
}
|
||||
|
||||
public void SendRT(byte[] buffer)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(buffer);
|
||||
}
|
||||
|
||||
public void SendRT(byte cmd, byte[] buffer)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(cmd, buffer);
|
||||
}
|
||||
|
||||
public void Send(string func, string funcCB, Delegate callback, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(func, funcCB, callback, pars);
|
||||
}
|
||||
|
||||
public void Send(string func, string funcCB, Delegate callback, int millisecondsDelay, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(func, funcCB, callback, millisecondsDelay, pars);
|
||||
}
|
||||
|
||||
public void Send(string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||
}
|
||||
|
||||
public void Send(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||
}
|
||||
|
||||
public void SendRT(string func, string funcCB, Delegate callback, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(func, funcCB, callback, pars);
|
||||
}
|
||||
|
||||
public void SendRT(string func, string funcCB, Delegate callback, int millisecondsDelay, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(func, funcCB, callback, millisecondsDelay, pars);
|
||||
}
|
||||
|
||||
public void SendRT(string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||
}
|
||||
|
||||
public void SendRT(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, pars);
|
||||
}
|
||||
|
||||
public void Send(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, SynchronizationContext context, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).Send(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, context, pars);
|
||||
}
|
||||
|
||||
public void SendRT(byte cmd, string func, string funcCB, Delegate callback, int millisecondsDelay, Action outTimeAct, SynchronizationContext context, params object[] pars)
|
||||
{
|
||||
((ISendHandle)_client).SendRT(cmd, func, funcCB, callback, millisecondsDelay, outTimeAct, context, pars);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
36
Assets/Plugins/GameDesigner/Component/Manager/NetworkTime.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
namespace Net.Component
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 网络时间中心控制, 控制发送频率, 不能乱来发送! 一个行为一秒可以发送30次同步
|
||||
/// </summary>
|
||||
public class NetworkTime : SingleCase<NetworkTime>
|
||||
{
|
||||
private float time;
|
||||
private static bool canSent;
|
||||
/// <summary>
|
||||
/// 当前是否可以发送数据? 这里可以控制发送次数, 一秒30帧数据左右
|
||||
/// </summary>
|
||||
public static bool CanSent { get { return canSent; } }
|
||||
/// <summary>
|
||||
/// 设置可发送时间 默认30次/秒
|
||||
/// </summary>
|
||||
public float CanSentTime = 1f / 30f;
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Time.time > time)
|
||||
{
|
||||
time = Time.time + CanSentTime;
|
||||
canSent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
canSent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,50 @@
|
||||
#if UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WSA || UNITY_WEBGL
|
||||
using System;
|
||||
|
||||
namespace Net.Component
|
||||
{
|
||||
public enum SerializeAdapterType
|
||||
{
|
||||
Default,//默认序列化, protobuff + json
|
||||
PB_JSON_FAST,//快速序列化 protobuff + json
|
||||
Binary,//快速序列化 需要注册远程类型
|
||||
Binary2,//极速序列化 Binary + Binary2 需要生成序列化类型, 菜单GameDesigner/Netowrk/Fast2BuildTools
|
||||
Binary3//极速序列化 需要生成序列化类型, 菜单GameDesigner/Netowrk/Fast2BuildTools
|
||||
}
|
||||
|
||||
[Obsolete("此组件已弃用, 内部已自动匹配适配器, 无需手动处理")]
|
||||
public class SerializeAdapter : SingleCase<SerializeAdapter>
|
||||
{
|
||||
public SerializeAdapterType type;
|
||||
public bool isEncrypt = false;//数据加密?
|
||||
public int password = 758426581;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
Init();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
var cm = GetComponent<ClientManager>();
|
||||
switch (type) {
|
||||
case SerializeAdapterType.Default:
|
||||
break;
|
||||
case SerializeAdapterType.PB_JSON_FAST:
|
||||
cm.client.AddAdapter(new Adapter.SerializeFastAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
case SerializeAdapterType.Binary:
|
||||
cm.client.AddAdapter(new Adapter.SerializeAdapter() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
case SerializeAdapterType.Binary2:
|
||||
cm.client.AddAdapter(new Adapter.SerializeAdapter2() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
case SerializeAdapterType.Binary3:
|
||||
cm.client.AddAdapter(new Adapter.SerializeAdapter3() { IsEncrypt = isEncrypt, Password = password });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
355
Assets/Plugins/GameDesigner/Component/OtherExt/MathExt.cs
Normal file
@@ -0,0 +1,355 @@
|
||||
using System;
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
public static class MathExt
|
||||
{
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref byte self, int value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked((byte)(self + value)),
|
||||
1 => checked((byte)(self - value)),
|
||||
2 => checked((byte)(self * value)),
|
||||
3 => checked((byte)(self / value)),
|
||||
4 => checked((byte)(self % value)),
|
||||
5 => checked((byte)(self ^ value)),
|
||||
6 => checked((byte)(self & value)),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref sbyte self, int value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked((sbyte)(self + value)),
|
||||
1 => checked((sbyte)(self - value)),
|
||||
2 => checked((sbyte)(self * value)),
|
||||
3 => checked((sbyte)(self / value)),
|
||||
4 => checked((sbyte)(self % value)),
|
||||
5 => checked((sbyte)(self ^ value)),
|
||||
6 => checked((sbyte)(self & value)),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref short self, int value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked((short)(self + value)),
|
||||
1 => checked((short)(self - value)),
|
||||
2 => checked((short)(self * value)),
|
||||
3 => checked((short)(self / value)),
|
||||
4 => checked((short)(self % value)),
|
||||
5 => checked((short)(self ^ value)),
|
||||
6 => checked((short)(self & value)),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref ushort self, int value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked((ushort)(self + value)),
|
||||
1 => checked((ushort)(self - value)),
|
||||
2 => checked((ushort)(self * value)),
|
||||
3 => checked((ushort)(self / value)),
|
||||
4 => checked((ushort)(self % value)),
|
||||
5 => checked((ushort)(self ^ value)),
|
||||
6 => checked((ushort)(self & value)),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static int CalcRef(this ref int self, int value, byte oper)
|
||||
{
|
||||
return self = Calc(self, value, oper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static int Calc(this int self, int value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked(self + value),
|
||||
1 => checked(self - value),
|
||||
2 => checked(self * value),
|
||||
3 => checked(self / value),
|
||||
4 => checked(self % value),
|
||||
5 => checked(self ^ value),
|
||||
6 => checked(self & value),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref uint self, uint value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked(self + value),
|
||||
1 => checked(self - value),
|
||||
2 => checked(self * value),
|
||||
3 => checked(self / value),
|
||||
4 => checked(self % value),
|
||||
5 => checked(self ^ value),
|
||||
6 => checked(self & value),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref float self, float value, byte oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
checked
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => self + value,
|
||||
1 => self - value,
|
||||
2 => self * value,
|
||||
3 => self / value,
|
||||
4 => self % value,
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref long self, int value, int oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked(self + value),
|
||||
1 => checked(self - value),
|
||||
2 => checked(self * value),
|
||||
3 => checked(self / value),
|
||||
4 => checked(self % value),
|
||||
5 => checked(self ^ value),
|
||||
6 => checked(self & value),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref ulong self, ulong value, int oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked(self + value),
|
||||
1 => checked(self - value),
|
||||
2 => checked(self * value),
|
||||
3 => checked(self / value),
|
||||
4 => checked(self % value),
|
||||
5 => checked(self ^ value),
|
||||
6 => checked(self & value),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref double self, double value, int oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked(self + value),
|
||||
1 => checked(self - value),
|
||||
2 => checked(self * value),
|
||||
3 => checked(self / value),
|
||||
4 => checked(self % value),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ɶ<EFBFBD><C9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="oper">0<><30><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> 2<><32><EFBFBD><EFBFBD> 3<><33><EFBFBD><EFBFBD> 4<><34>ȡģ 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 6<><36><EFBFBD><EFBFBD></param>
|
||||
/// <returns></returns>
|
||||
public static bool Calc(this ref decimal self, decimal value, int oper)
|
||||
{
|
||||
try
|
||||
{
|
||||
self = oper switch
|
||||
{
|
||||
0 => checked(self + value),
|
||||
1 => checked(self - value),
|
||||
2 => checked(self * value),
|
||||
3 => checked(self / value),
|
||||
4 => checked(self % value),
|
||||
_ => throw new Exception("û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Net.Event.NDebug.LogError("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:" + ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
|
||||
public static class SystemBaseExt
|
||||
{
|
||||
public static string FormatCoin(this int self)
|
||||
{
|
||||
return FormatCoin((long)self);
|
||||
}
|
||||
|
||||
public static string FormatCoin(this long self)
|
||||
{
|
||||
double size = self;
|
||||
string[] units = new string[] { "B", "K", "M", "G", "T", "P" };
|
||||
double mod = 1000;
|
||||
int i = 0;
|
||||
while (size >= mod)
|
||||
{
|
||||
size /= mod;
|
||||
i++;
|
||||
}
|
||||
return Math.Round(size, 2) + units[i];
|
||||
}
|
||||
|
||||
public static string FormatRMB(this int self)
|
||||
{
|
||||
return FormatRMB((long)self);
|
||||
}
|
||||
|
||||
public static string FormatRMB(this long self)
|
||||
{
|
||||
double value = self;
|
||||
if (value < 1000d)
|
||||
{
|
||||
return value.ToString("f0");// + "$";
|
||||
}
|
||||
if (value < 10000d)
|
||||
{
|
||||
value /= 1000d;
|
||||
var str = value.ToString("0.##");
|
||||
return str + "千";
|
||||
}
|
||||
|
||||
if (value < 100000000d)//1w-1e显示为0.n万
|
||||
{
|
||||
value /= 10000d;
|
||||
var str = value.ToString("0.##");
|
||||
return str + "万";
|
||||
}
|
||||
|
||||
if (value < 1000000000000d)//1e-1m显示为0.n亿
|
||||
{
|
||||
value /= 100000000d;
|
||||
var str = value.ToString("0.##");
|
||||
return str + "亿";
|
||||
}
|
||||
|
||||
if (value < 10000000000000000d)//1m-1g显示为0.n兆
|
||||
{
|
||||
value /= 1000000000000d;
|
||||
var str = value.ToString("0.##");
|
||||
return str + "兆";
|
||||
}
|
||||
|
||||
if (value < 100000000000000000000d)//1g-1t显示为0.n京
|
||||
{
|
||||
value /= 10000000000000000d;
|
||||
var str = value.ToString("0.##");
|
||||
return str + "京";
|
||||
}
|
||||
|
||||
{
|
||||
value /= 100000000000000000000d;
|
||||
var str = value.ToString("0.##");
|
||||
return str + "稊";
|
||||
}
|
||||
}
|
||||
}
|