==========================================SendMessage***=========================================
Unity里面的SendMessage是一个非常好用的方法,他的调用方式是 gameobject.SendMessage(“MethodName”,object t); 他会查找当前物体里面所有的脚本,并且根据反射查找与方法名和参数列表一致的方法并且执行,我一般会将其用在动画状态之中
如上,如果我想要在动画执行开始,或是执行过程中执行某个方法,就可以直接添加一个Method,代码中会自动帮我执行这个方法,当然,前提是我必须要有这个公共方法。
好处:执行起来方便,调用简单,不需要我们写那么多的代码去完成一个委托或是反射
坏处:执行花费内存比较大(毕竟你知道目标在哪,和一个个问差别还是蛮大的),如果动画状态过多,或是使用较多,一旦方法出现BUG,查找起来会很麻烦
=========================================动画中的Event==========================================
动画中的Event和SendMessage差不多,都是查找本物体的公共方法,但是动画中的Event拥有自己的曲线,我们可以选择性的决定他什么时候,什么帧数执行
选择你需要放置事件的动画,将滚动条拉到低端
可以看到,我们可以直接控制动画的播放,让其在我们需要的地方添加执行的事件,注:当你创建事件并设置好参数时,记得点一下Apply
========================================Animation事件=============================================
有一些老版的动画是没有办法设置Event的,这个时候我们就必须自己找到Animation组件去设置事件,方法为先打开Animation创建面板 Window => Animation ,之后选中Project面板中你想要设置事件的动画,注:有一些动画会出现一个ReadOnly的状态无法设置动画,这个时候只要选中Project中的动画,Ctrl+D复制一份,在复制体上添加事件就可以了,但是相应的你场景中的相应AnimationClip也要更换为复制体
与Animator Event类似,老版的动画事件也是必须要在本物体里面有相应的公共方法,否则抛出异常
================================================Delegate=========================================
委托:简单来说 委托就是一个类 他可以接受其他的方法作为参数 加入到自己的列表中,当执行委托时,他旗下的所有方法会被一起执行,并且参数通用↓
using ...;
public class DelegateEvent
{
public static DelegateEventInstance{get;}
private Delegate void Print(string info); // 声明一个委托 无返回值 stirng参数
public Print print();//实例化
public void AddEvent(Print e)
{
print += e;
}
public void DelEvent(Print e)
{
print -= e;
}
public void Play()
{
print();
}
}
==================================================
using ...;
public class Test:Mono
{
void Awake()
{
for(int i = 0;i < 10;i++)
Instantiate<GameObject>(Resources...); // 假设这些物体上面都有一个print脚本
}
void Start()
{
DelegateEvent.Instance.Play("hello world");
}
}
==================================================
using ...;
public class print:Mono
{
void Awake()
{
Test.Instance.AddEvent(print);
}
public void print(string info)
{
Debug.Log(info);
}
}
当运行之后,你会看到10个hello world,这种方法极大的简化了我们的工作流程,毕竟我们不需要保存生成的物体,也不需要他的实例化,只需要把我需要的方法在我执行之前加入进来即可
============================================线程===============================================
- -这个是一时兴起加的,虽然加上后让整个标题都怪怪的 - -
Unity里面并不支持多线程,他所自带的携程 IEnumerator 其实也是顺序执行,只是在每一帧结束后会去查看携程中的条件是否满足,从根本上来说,这其实也只是一个伪线程,不信的话你可以写上这么一段
public class Test: MonoBehaviour {
void Start () {
StartCoroutine(true());
}
IEnumerator test()
{
while (true)
{
Debug.Log("11");
}
}
}
不出意外的话,Unity会直接失去响应,因为Unity发现,他的条件一直为真,所以就一直在执行,当然,是在Main线程中。
而多线程通俗来说就是本来只有一条路,现在我给你另外一条路,你去哪里跑,无论你是堵死还是瞬间结束都与我无关。
线程的使用是方法的调用
void Test()
{
Thread thread = new Thread(() => {
//方法体 匿名表达式 也叫Lambda表达式
});
Thread thread2 = new Thread(test1); // 注:方法没有返回值 参数必须是object类型
}
void test1(object s)
{
while (true)
{
//这里不能用任何Unity相关的东西
//Debug都不行,就算你在Editor里面不出错,但是当你打包之后有很大可能出现一个GC错误
//从而导致无法运行
}
}
这里,就有小伙伴要问了,Unity相关的都无法使用那要他有什么用=>当然是超大量的计算啊,或是必须实时接受数据的那种
比如说Socket里面的
using ...;
class ReceiveMessage
{
public Socket Client;
public void Initial()
{
Client = New Socket
(
...;//初始化
);
Client.Connect(new IpEndPoint(ip,Port));
Thread receiveMessage = new Thread();
receiveMessage.IsBackGround = true;
//设为后台线程,就是游戏进入后台运行也可以继续执行 和 Unity里面
//Application.RunInBackground(将Unity主线程设为后台运行)一致
receiveMessage.Start;
}
public void Receive()
{
while(true)
{
// 如果有信息传入 ↓ 就会往下执行 否则continue;
int mesLength = client.Receive(result);
// 执行委托中的方法 参数为result
ReceiveEvent.Instance.play(Encoding.UTF8.GetString(result, 0, mesLength));
//处理代码
}
}
}
///委托
class ReceiveEvent
{
public static ReceiveEvent Instance{get;}
public delegate void dele(string info);
private dele Receive;
public void AddEvent(dele e)
{
Receive += e;
}
public void Play()
{
Receive();
}
}
///场景物体中的脚本
class Test : Mono...
{
void Awake()
{
}
void print(string info)
{
Debug.Log("来自服务器的消息:"+info);
}
}
!--这个例子比较简单
class Test :Mono...{
public Vector3 v; //在外部更改这个值
void Test()
{
Thread thread = new Thread(() => {
//方法体
});
Thread thread2 = new Thread(test1);
}
void test1(object s)
{
while (true)
{
v = (Vector3)s + new Vector3(1,1,1s);
}
}
private void Update()
{
transform.position = v;
}
}