触发器与碰撞器 Trigger & Collider:
Unity中的物体可以根据双方的触发器与碰撞器产生交互。 触发器与碰撞器有三种不同的状态,Enter,Stay与Exit。
1 2 3 4 5 6 7 8 private void OnTriggerEnter (Collider other )private void OnTriggerStay (Collider other )private void OnTriggerExit (Collider other )private void OnCollisionEnter (Collision collision )private void OnCollisionStay (Collision collision )private void OnCollisionExit (Collision collision )
不同的移动方法与触发器和碰撞器产生的交互也不相同:
Math Function:
遇到目标即使是碰撞器,依然穿透
不管自身是否是碰撞器或者触发器,当它接触到目标的时候(碰撞器/触发器),此时交互没有反应
Character Controller:
碰撞器:有阻挡效果,没有办法接收碰撞器Collision事件
触发器:可穿透,可以接收Tigger事件
Rigidbody:
刚体自身的Collider如果是碰撞器,则只响应碰撞器事件。
刚体自身的Collider如果是触发器,则同时响应碰撞器和触发器事件。
角色交互 NPC Interaction: 实现角色之间的交互,当玩家接近NPC时,NPC会面向玩家。当玩家远离NPC时,NPC会回归自己的朝向。
当NPC的触发器与玩家接触时(Enter),调用OnTriggerEnter(),修改枚举状态。 计算NPC到玩家的方向向量,将NPC旋转指向玩家。
当NPC的触发器与玩家分离时(Exit), 调用OnTriggerExit(),修改枚举状态。 将NPC的方向恢复到原有的方向向量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 using System.Collections;using System.Collections.Generic;using UnityEngine;public class NPC : MonoBehaviour { public enum emTriggerType { None, Enter, Exit, } private Transform m_tfPlayer; private emTriggerType m_emTriggerType; private float m_fRotateSpeed; private float m_fTimer; private Quaternion m_srcRotation; void Start () { m_tfPlayer = GameObject.FindObjectOfType<Player>().transform; m_emTriggerType = emTriggerType.None; m_fRotateSpeed = 3f ; m_fTimer = 0f ; m_srcRotation = transform.rotation; SphereCollider trigger = transform.gameObject.AddComponent<SphereCollider>(); trigger.isTrigger = true ; trigger.radius = 10f ; } void Update () { if (m_emTriggerType == emTriggerType.Enter) { Vector3 dir = m_tfPlayer.transform.position - transform.position; Quaternion targetQ = Quaternion.LookRotation(dir, Vector3.up); transform.rotation = Quaternion.Lerp(transform.rotation, targetQ, Time.deltaTime * m_fRotateSpeed); m_fTimer += Time.deltaTime; if (m_fTimer >= 1f ) { m_emTriggerType = emTriggerType.None; m_fTimer = 0 ; } } else if (m_emTriggerType == emTriggerType.Exit) { transform.rotation = Quaternion.Lerp(transform.rotation, m_srcRotation, Time.deltaTime * m_fRotateSpeed); m_fTimer += Time.deltaTime; if (m_fTimer >= 1f ) { m_emTriggerType = emTriggerType.None; m_fTimer = 0 ; } } } private void OnTriggerEnter (Collider other ) { if (other.transform != m_tfPlayer) return ; m_emTriggerType = emTriggerType.Enter; } private void OnTriggerExit (Collider other ) { if (other.transform != m_tfPlayer) return ; m_emTriggerType = emTriggerType.Exit; } }
UI元素添加 UI Component: 添加UI组件: 调用Resource下的相对路径文件。 导入UnityEngine.UI包。
将UI对象实例化,并挂载到附节点上。 从Resource中获得Text,Image等UI对象。
根据场景决定显示NPC名字还是HP血条。
在进行显示时,需要将NPC和玩家的世界坐标系位置转化到屏幕坐标系,将名字显示在屏幕。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI; public class Unity_Entity : MonoBehaviour { private GameObject m_objModel; private Text m_txtCharacterName; private GameObject m_objHPBar; private Image m_imgHP; public Vector3 mv3Offset; void Start () { GameObject uiUnit = Resources.Load<GameObject>("Prefabs/UI/Unit_Entity" ); uiUnit.SetActive(false ); mv3Offset = new Vector3(0f , 2f , 0f ); m_objModel = Instantiate<GameObject>(uiUnit); m_objModel.transform.parent = GameObject.Find("UnitEntityRoot" ).transform; m_txtCharacterName = m_objModel.transform.Find("Context/txtCharacterName" ).GetComponent<Text>(); m_objHPBar = m_objModel.transform.Find("Context/HPBar" ).gameObject; m_imgHP = m_objModel.transform.Find("Context/HPBar/hp" ).GetComponent<Image>(); m_txtCharacterName.text = this .gameObject.name; m_objHPBar.SetActive(!SceneManager.Instance.isMainScene); } void Update () { m_objModel.transform.position = Camera.main.WorldToScreenPoint(this .transform.position + mv3Offset); } }
为了判断我们的场景,我们需要创建一个SceneManager并挂载到Manager上。 当当前场景是主场景时返回true。
场景判断: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 using System.Collections;using System.Collections.Generic;using UnityEngine;public class SceneManager : MonoBehaviour { public static SceneManager Instance; public bool isMainScene { get { UnityEngine.SceneManagement.Scene curScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); return curScene.name == "MainScene" ; } } void Awake () { Instance = this ; } void Update () { } }