渲染模式改为世界空间
导入面板组件并通过画布调整大小
在面板上导入文本组件,显示玩家名称(旧版)
为了使血条填满,Fill Area 数值全部置为0
改变背景颜色和填充物颜色,并设置血条方向
改变数值方便计算
绑定文本组件和滑动条组件
创建一个空物体,加Respawn标签,意为复活点
可以在此处旋转标记,该处标记只有程序员能看见
绑定复活效果特效
PlayerHealth脚本(绑定在人物身上)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
-
- public class PlayerHealth : MonoBehaviour
- {
- public Text nameText;//玩家名称
- public Slider healthSlider;
- public float maxHp = 100;
- public float minHp = 0;
- public float currentHp;//当前的血量
- public Transform RespawnPoint;//重生点
- public GameObject respawnVFX;//重生特效
- void Start()
- {
- if (RespawnPoint == null)
- {
- RespawnPoint = GameObject.FindGameObjectWithTag("Respawn").transform;
- }
- if (nameText == null || healthSlider == null||respawnVFX==null)
- {
- Debug.LogError("请检查文本或滑动条组件或重生特效粒子拽了没");
- }
- if (nameText != null)
- {
- nameText.text = "玩家小组名称";
- }
- currentHp = maxHp;//开始满血
- if (healthSlider != null)
- {
- healthSlider.maxValue = maxHp;
- healthSlider.value = currentHp;
- }
- }
-
- public void TakeDamage(float damage)
- {
- if (currentHp == 0)
- {
- return;
- }
- if (currentHp > damage)
- {
- currentHp -= damage;
- }
- else
- {
- currentHp = 0;
- }
-
- if (currentHp == 0)
- {
- print("死掉咯");
- //隐藏玩家
- gameObject.SetActive(false);
- //延迟调用
- //Invoke("PlayerRespawn", 5f);
- PlayerRespawn();
- }
-
- healthSlider.value = currentHp;
- }
-
- //
- void ShowPlayer()
- {
- gameObject.SetActive(true);
- }
- //玩家死亡重生后
- public void PlayerRespawn()
- {
- currentHp = 100;
- //同步UI数据
- healthSlider.value = currentHp;
-
- //玩家瞬移到重生点,并实例化重生特效
- if (RespawnPoint != null)
- {
- transform.position = RespawnPoint.position;
- if (respawnVFX != null)
- {
- //实例化特效粒子
- GameObject respawnEffect = Instantiate(respawnVFX, transform.position, Quaternion.identity);
- Invoke("ShowPlayer", 2f);
- Destroy(respawnEffect,4f);
-
- }
- }
- }
-
- }
CanPickUpItem脚本(绑定在玩家身上)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class CanPickUpItem : MonoBehaviour
- {
-
- public bool isNear = false;//玩家是否在附近
- public Transform rHandItemPos;//玩家右手位置
- public bool rHandIsHasItem=false;//玩家手中是否有道具
-
- private void Start()
- {
- if (rHandItemPos == null)
- {
- Debug.LogError("检查参数栏,道具位置物体没有拽入");
- }
- }
- private void OnTriggerEnter(Collider other)
- {
- if(other.CompareTag("Player"))
- {
- isNear = true;
- }
- }
- private void OnTriggerExit(Collider other)
- {
- if (other.CompareTag("Player"))
- {
- isNear = false;
- }
-
- }
- private void Update()
- {
- //如果玩家到达附加并且按下键盘上的E键,拾取道具
- if(isNear && Input.GetKeyDown(KeyCode.E))
- {
- if(!rHandIsHasItem)
- {
- PickUpItem();
- }
- /* else
- {
- Debug.LogError("玩家手里已经有了其他道具,不能重复拾取");
- }*/
- }
- if(Input.GetKeyDown(KeyCode.G)&&rHandIsHasItem)
- {
- DisCardItem();
- }
- }
- //拾取道具(坐标的转移)
- void PickUpItem()
- {
- rHandIsHasItem = true;
- transform.position=rHandItemPos.position;//位置转移
- transform.rotation=rHandItemPos.rotation;//角度转移
- //打开刚体的忽略物理学运算开关
- transform.GetComponent
().isKinematic = true; - //关闭碰撞器开关
- transform.GetComponent
().enabled=false; - //关闭触发器开关
- transform.GetComponent
().enabled=false; -
- //把玩家的手和道具绑定在一起(设置右手位置物体,为道具的父物体)
- transform.SetParent(rHandItemPos);
-
- }
- //丢弃道具
- void DisCardItem()
- {
- if(rHandIsHasItem)
- {
- rHandIsHasItem = false;
- //关闭刚体的忽略物理学运算开关
- transform.GetComponent
().isKinematic = false; - //加力
- transform.GetComponent
().AddForce(Vector3.forward*2000f); - //打开碰撞器开关
- transform.GetComponent
().enabled = true; - //打开触发器开关
- transform.GetComponent
().enabled = true; -
- //把玩家的手和道具解绑
- transform.SetParent(null);
- }
-
-
- }
- }
CameraMove脚本(绑定在摄像机身上)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- ///
- /// 第三人称摄像机简单版
- ///
- public class CameraMove : MonoBehaviour
- {
- public Transform target;//摄像机的跟随目标
- public float distance = 8.0f;//摄像机与目标之间的距离
- private float x, y, z;
- private float xSpeed = 250.0f;
- private float ySpeed = 120.0f;
- //限制上下移动角度
- public float yMinlimit = -45.0f;
- public float yMaxlimit = 45.0f;
-
- /* private void Awake()
- {
- //注册场景加载完毕事件
- EventCenter.AddListener(EventType.SceneLoadComplete, SetTarget);
- }*/
-
- private void SetTarget()
- {
- //将标签为Player的物体设置为跟踪目标
- Transform player = GameObject.FindGameObjectWithTag("Player").transform;
- if (player != null && target == null)
- target = player;
- }
- private void Start()
- {
- Vector3 angles = transform.eulerAngles;//获取摄像机的当前角度
- x = angles.x;
- y = angles.y;
- z = -distance;
- GoRight();
- }
-
- private void LateUpdate()
- {
- float temp = Input.GetAxis("Mouse ScrollWheel");//获取滚轮数值
- if (target != null)
- {
- if (Input.GetMouseButton(0))
- {
- x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
- y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
- }
- /*
- else if (Input.GetMouseButton(1))
- {
- x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
- y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
- //影响玩家的Y轴旋转角度
- target.rotation = Quaternion.Euler(target.rotation.x,x,target.rotation.z);
- }
- */
- }
- //钳制上下移动的角度
- y = ClampAngle(y,yMinlimit,yMaxlimit);
- z += temp * 100f * 0.02f;//数值按照自己喜好设定
- z = Mathf.Clamp(z,-20f,-3.0f);//距离限制,最远是距离玩家20米,最近是3米
- GoRight();//作用于摄像机
- }
-
- float ClampAngle(float angle,float min,float max)
- {
- if (angle < -360)
- angle += 360;
- if (angle > 360)
- angle -= 360;
- return Mathf.Clamp(angle,min,max);
- }
- //摄像机控制位置及角度的核心方法
- void GoRight()
- {
- if (target == null)
- return;
- Quaternion rotation = Quaternion.Euler(y,x,0);//摄像机角度
- Vector3 position = rotation * new Vector3(0.0f,0.0f,z)+target.position;
- transform.position = position;//摄像机位置
- transform.rotation = rotation;//摄像机角度
- }
- }
MonsterAI脚本(绑定在怪物身上)
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using static UnityEditor.FilePathAttribute;
-
- public enum MonstorAIState
- {
- idle,//闲置状态
- Patrol,//巡逻
- ChasePlayer,//追击玩家
- AttackPlayer,//攻击玩家
- //自己添加其他状态
-
- }
-
- public class MonsterAI : MonoBehaviour
- {
- public float speed = 2f;//移动速度
- public Transform[] wayPointArr;//路径点数组
- public Transform pathObj;//路径点父物体
- //当前的路径点下标
- public int currentWaypointIndex = 0;
- private Animator _animator;//动画器
- public MonstorAIState monsterCurrentState=0;//怪物当前状态
- public MonstorAIState monsterOldState=0;
- private Transform playerObj;//玩家物体
- public bool isAlive=true;//丧尸是否活着
- public bool isFindPlayer = false;//是否发现玩家
-
- // Start is called before the first frame update
- void Start()
- {
- //在场景里通过标签查找玩家物体
- playerObj = GameObject.FindGameObjectWithTag("Player").transform;
- //判断玩家是否已经正确找到
- if(playerObj==null)
- {
- Debug.LogError("没有找到玩家物体,请查看玩家标签是否正确设置为Player");
-
- }
- _animator = GetComponent
();//获取动画器组件引用 -
- //自动搜索场景中的路径点加载到路径点数组中
- if (pathObj != null)
- {
- //数组开辟内存
- wayPointArr = new Transform[pathObj.childCount];
- for (int i = 0; i < pathObj.childCount; i++)
- {
- wayPointArr[i] = pathObj.GetChild(i).transform;
- }
- }
- else
- {
- Debug.LogError("路径点父物体没有拽入参数栏");
- }
-
- //开启协程
- StartCoroutine(IsFindPlayer(1f,25f));
- }
-
-
-
- // Update is called once per frame
- void Update()
- {
- //如果丧失已经死亡,则不郧西下面代码
- if (!isAlive)
- return;
- switch (monsterCurrentState)
- {
- case MonstorAIState.idle:
- Idle();
- break;
- case MonstorAIState.Patrol://巡逻状态
- Patrol();
- break;
- case MonstorAIState.ChasePlayer://追击玩家
- ChasePlayer();
- break;
- case MonstorAIState.AttackPlayer://追击玩家
- AttackPlayer();
- break;
- }
-
- }
-
- void Patrol()//巡逻状态
- {
- speed = 0.5f;
- _animator.SetFloat("moveSpeed",speed);
- //计算怪物与目标点之间的角度 并进行方向修正
- Vector3 direction = wayPointArr[currentWaypointIndex].position - transform.position;
- //计算旋转角度并旋转
- transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 0.1f);
- if (direction.sqrMagnitude < 0.02f)
- {
- if (currentWaypointIndex++ == wayPointArr.Length - 1)
- {
- currentWaypointIndex = 0;
- }
- }
- //一直前进
- transform.Translate(Vector3.forward * Time.deltaTime * speed);
- //播放动画
- _animator.SetFloat("moveSpeed", speed);
- }
-
- //闲置
- void Idle()
- {
- speed = 0;
- _animator.SetFloat("moveSpeed",speed);
- }
- //追击玩家方法
- void ChasePlayer()
- {
- speed = 0.8f;
- _animator.SetFloat("moveSpeed", speed);
- //面向玩家
- //计算与玩家的角度
- Vector3 direction = playerObj.position - transform.position;
- //计算旋转角度并旋转
- transform.rotation = Quaternion.Slerp(transform.rotation,
- Quaternion.LookRotation(direction),
- 0.1f);
- //一直前进
- transform.Translate(Vector3.forward * Time.deltaTime * speed);
- //播放动画
- _animator.SetFloat("moveSpeed", speed);
- //如果玩家与怪物之间的距离大于设定的N米,则返回旧状态
-
- if(direction.sqrMagnitude>10f*10f)
- {
- monsterCurrentState = monsterOldState;
- isFindPlayer = false;//玩家追丢了,重置
- }
- //查找玩家的协程有没有开启
-
- //如果玩家与怪物之间的距离小于设定的距离,则进入到攻击状态
- print(direction.sqrMagnitude);
- if(direction.sqrMagnitude<0.4f)
- {
- monsterCurrentState=MonstorAIState.AttackPlayer;//攻击玩家
- }
- }
- //通过与玩家距离来判断是否发现玩家
- IEnumerator IsFindPlayer(float intervalTime, float discoveryDistance)
- {
- while (isAlive)
- {
- if (!isFindPlayer && playerObj != null)
- {//计算与玩家的距离
- Vector3 direction = playerObj.position - transform.position;
- if (direction.sqrMagnitude < discoveryDistance*discoveryDistance)
- {
- //发现玩家
- print("怪物已经发现玩家!");
- isFindPlayer = true;
- //记录旧状态
- monsterOldState = monsterCurrentState;
- //将当前的怪物状态设置为追击玩家状态
- monsterCurrentState = MonstorAIState.ChasePlayer;
- }
- /* else
- {
- //将当前的怪物状态设置为闲置状态
- monsterCurrentState = MonstorAIState.idle;
- }*/
- }
- yield return new WaitForSeconds(intervalTime);
- }
-
- }
- void AttackPlayer()
- {
- speed = 0;
- _animator.SetFloat("moveSpeed", speed);
- _animator.SetTrigger("Attack");//播放攻击玩家动画
- //计算与玩家的距离
- Vector3 direction = playerObj.position - transform.position;
- if(direction.sqrMagnitude>0.4f)
- {
- monsterCurrentState = MonstorAIState.ChasePlayer;
- }
- }
- }
在距离小于3f时,调用伤害方法
MonsterAnimationEvent脚本(绑定在怪物身上)
- using System.Collections;
- using System.Collections.Generic;
- using Unity.VisualScripting;
- using UnityEngine;
-
- public class MonsterAnimationEvent : MonoBehaviour
- {
- public GameObject playerObj;
- private void Start()
- {
- if (playerObj == null)
- {
- playerObj = GameObject.FindGameObjectWithTag("Player");
- }
-
- }
-
- public void AttackPlayer(float damage)
- {
- if (playerObj != null)
- {
- float distance = Vector3.Distance(playerObj.transform.position, transform.position);
- // 打印距离
- Debug.Log(distance);
- if (distance < 3f)
- {
- playerObj.GetComponent
().TakeDamage(damage); - }
- }
- }
- }