unity基础1-事件执行顺序、自定义事件

事件执行顺序

在unity中,我们通过添加脚本来控制物体的行为,那么搞清楚脚本中事件的执行顺序就十分重要。详情参见官方文档

在这里插入图片描述
最常用的几个生命周期函数是:
部分代码片段来自 B 站麦扣老师的 3DRPG 课程的 playercontroller.cs 和 mousemanager.cs
Awake
例如,获取组件的引用

	void Awake()
    {
        agent = GetComponent<NavMeshAgent>();
        anim = GetComponent<Animator>();
        characterStats = GetComponent<CharacterStats>();
        stopDistance = agent.stoppingDistance;
    }

或者把当前脚本绑定的游戏物体,标记为切换场景时不删除

	protected override void Awake()
    {
        base.Awake();
        DontDestroyOnLoad(this);
    }

OnEnable
为某些事件绑定处理函数

	void OnEnable()
    {
        MouseManager.Instance.OnMouseClick += MoveToTarget;
        MouseManager.Instance.OnEnemyClick += EventAttack;
        GameManager.Instance.RegisterPlayer(characterStats);
    }

Update
处理游戏的输入、状态的切换等

	void Update()
    {
        isDead = characterStats.CurrentHealth == 0;
        if (isDead)
        {
            GameManager.Instance.NotifyObservers();
        }
        SwitchAnimation();
        lastAttackTime -= Time.deltaTime;
    }

OnDisable
为某些事件注销处理函数

	void OnDisable()
    {
        MouseManager.Instance.OnMouseClick -= MoveToTarget;
        MouseManager.Instance.OnEnemyClick -= EventAttack;
    }

OnDestroy

	protected virtual void OnDestory()
    {
        if (instance == this)
        {
            instance = null;
        }
    }

FixUpdate
用于物理状态更新,固定的帧间隔使物理效果更真实
LateUpdate
用于相机跟随,只有最后一帧才需要更新相机的位置,前面几帧可以只更新物体位置等信息。

自定义事件

有时候我们需要在生命周期事件以外,自定义事件,例如,用一个图片代替鼠标时,从图片位置发射射线判断点击的物品,定义自己的鼠标点击事件处理不同的逻辑,需要事件名 OnMouseClick 和事件处理函数需要的参数类型 Vector3

法一:继承 UnityEvent<T> 泛型类,定义自己的事件类,优点是可以编辑器在 inspector 窗口在添加事件处理函数,就像是 UI Button 按钮的点击事件一样
在这里插入图片描述

	using UnityEngine.Events;

	[Serializable]
	public class EventVector3 : UnityEvent<Vector3> { }

声明自定义事件

public class MouseManager : Singleton<MouseManager>
{
    RaycastHit hitInfo;
    public EventVector3 OnMouseClick;
    // 或者直接使用 UnityEvent
    // public UnityEvent OnGameFinish;
    ...
}

法二:使用 Csharp 的委托 Action 定义自己的事件,优点是使用方便

public class MouseManager : Singleton<MouseManager>
{
    RaycastHit hitInfo;
    // public EventVector3 OnMouseClick;
    public event Action<Vector3> OnMouseClick;
    public event Action<GameObject> OnEnemyClick;
	...
}

绑定和移除事件处理函数

	void OnEnable()
    {
        MouseManager.Instance.OnMouseClick += MoveToTarget;
        MouseManager.Instance.OnEnemyClick += EventAttack;
        GameManager.Instance.RegisterPlayer(characterStats);
    }
    void OnDisable()
    {
        MouseManager.Instance.OnMouseClick -= MoveToTarget;
        MouseManager.Instance.OnEnemyClick -= EventAttack;
    }

呼叫事件

	void MouseControl()
    {
        if (Input.GetMouseButtonDown(0) && hitInfo.collider != null)
        {
            if (hitInfo.collider.gameObject.CompareTag("Ground"))
            {
                OnMouseClick?.Invoke(hitInfo.point);
            }
            else if (hitInfo.collider.gameObject.CompareTag("Enemy"))
            {
                OnEnemyClick?.Invoke(hitInfo.collider.gameObject);
            }
            else if (hitInfo.collider.gameObject.CompareTag("Attackable"))
            {
                OnEnemyClick?.Invoke(hitInfo.collider.gameObject);
            }
            else if (hitInfo.collider.gameObject.CompareTag("Protal"))
            {
                OnMouseClick?.Invoke(hitInfo.point);
            }
        }
    }

剩余部分的代码,就是在 update 中发射射线

	void Update()
    {
        SetCursorTexture();
        MouseControl();
    }

    void SetCursorTexture()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hitInfo))
        {
            // 切换鼠标贴图
            switch (hitInfo.collider.gameObject.tag)
            {
                case "Ground":
                    Cursor.SetCursor(target, new Vector2(16, 16), CursorMode.Auto);
                    break;
                case "Enemy":
                    Cursor.SetCursor(attack, new Vector2(16, 16), CursorMode.Auto);
                    break;
                case "Protal":
                    Cursor.SetCursor(doorway, new Vector2(16, 16), CursorMode.Auto);
                    break;
                default:
                    Cursor.SetCursor(arrow, new Vector2(16, 16), CursorMode.Auto);
                    break;
            }
        }
    }
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值