Unity 常用的事件类型及其用法和线程

==========================================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;
    }
}

 

猜你喜欢

转载自blog.csdn.net/MikuLingSSS/article/details/82357104