• 个人课设---玩家血条(包括攻击掉血,复活重生功能)


    血条UI操作

    渲染模式改为世界空间

    导入面板组件并通过画布调整大小

    在面板上导入文本组件,显示玩家名称(旧版)

    为了使血条填满,Fill Area 数值全部置为0

    改变背景颜色和填充物颜色,并设置血条方向

    改变数值方便计算

    绑定文本组件和滑动条组件

    复活

    创建一个空物体,加Respawn标签,意为复活点

    可以在此处旋转标记,该处标记只有程序员能看见 

     

    绑定复活效果特效

    代码

    掉血,重生

    PlayerHealth脚本(绑定在人物身上)

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. public class PlayerHealth : MonoBehaviour
    6. {
    7. public Text nameText;//玩家名称
    8. public Slider healthSlider;
    9. public float maxHp = 100;
    10. public float minHp = 0;
    11. public float currentHp;//当前的血量
    12. public Transform RespawnPoint;//重生点
    13. public GameObject respawnVFX;//重生特效
    14. void Start()
    15. {
    16. if (RespawnPoint == null)
    17. {
    18. RespawnPoint = GameObject.FindGameObjectWithTag("Respawn").transform;
    19. }
    20. if (nameText == null || healthSlider == null||respawnVFX==null)
    21. {
    22. Debug.LogError("请检查文本或滑动条组件或重生特效粒子拽了没");
    23. }
    24. if (nameText != null)
    25. {
    26. nameText.text = "玩家小组名称";
    27. }
    28. currentHp = maxHp;//开始满血
    29. if (healthSlider != null)
    30. {
    31. healthSlider.maxValue = maxHp;
    32. healthSlider.value = currentHp;
    33. }
    34. }
    35. public void TakeDamage(float damage)
    36. {
    37. if (currentHp == 0)
    38. {
    39. return;
    40. }
    41. if (currentHp > damage)
    42. {
    43. currentHp -= damage;
    44. }
    45. else
    46. {
    47. currentHp = 0;
    48. }
    49. if (currentHp == 0)
    50. {
    51. print("死掉咯");
    52. //隐藏玩家
    53. gameObject.SetActive(false);
    54. //延迟调用
    55. //Invoke("PlayerRespawn", 5f);
    56. PlayerRespawn();
    57. }
    58. healthSlider.value = currentHp;
    59. }
    60. //
    61. void ShowPlayer()
    62. {
    63. gameObject.SetActive(true);
    64. }
    65. //玩家死亡重生后
    66. public void PlayerRespawn()
    67. {
    68. currentHp = 100;
    69. //同步UI数据
    70. healthSlider.value = currentHp;
    71. //玩家瞬移到重生点,并实例化重生特效
    72. if (RespawnPoint != null)
    73. {
    74. transform.position = RespawnPoint.position;
    75. if (respawnVFX != null)
    76. {
    77. //实例化特效粒子
    78. GameObject respawnEffect = Instantiate(respawnVFX, transform.position, Quaternion.identity);
    79. Invoke("ShowPlayer", 2f);
    80. Destroy(respawnEffect,4f);
    81. }
    82. }
    83. }
    84. }

    捡起丢弃道具

    CanPickUpItem脚本(绑定在玩家身上)

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class CanPickUpItem : MonoBehaviour
    5. {
    6. public bool isNear = false;//玩家是否在附近
    7. public Transform rHandItemPos;//玩家右手位置
    8. public bool rHandIsHasItem=false;//玩家手中是否有道具
    9. private void Start()
    10. {
    11. if (rHandItemPos == null)
    12. {
    13. Debug.LogError("检查参数栏,道具位置物体没有拽入");
    14. }
    15. }
    16. private void OnTriggerEnter(Collider other)
    17. {
    18. if(other.CompareTag("Player"))
    19. {
    20. isNear = true;
    21. }
    22. }
    23. private void OnTriggerExit(Collider other)
    24. {
    25. if (other.CompareTag("Player"))
    26. {
    27. isNear = false;
    28. }
    29. }
    30. private void Update()
    31. {
    32. //如果玩家到达附加并且按下键盘上的E键,拾取道具
    33. if(isNear && Input.GetKeyDown(KeyCode.E))
    34. {
    35. if(!rHandIsHasItem)
    36. {
    37. PickUpItem();
    38. }
    39. /* else
    40. {
    41. Debug.LogError("玩家手里已经有了其他道具,不能重复拾取");
    42. }*/
    43. }
    44. if(Input.GetKeyDown(KeyCode.G)&&rHandIsHasItem)
    45. {
    46. DisCardItem();
    47. }
    48. }
    49. //拾取道具(坐标的转移)
    50. void PickUpItem()
    51. {
    52. rHandIsHasItem = true;
    53. transform.position=rHandItemPos.position;//位置转移
    54. transform.rotation=rHandItemPos.rotation;//角度转移
    55. //打开刚体的忽略物理学运算开关
    56. transform.GetComponent().isKinematic = true;
    57. //关闭碰撞器开关
    58. transform.GetComponent().enabled=false;
    59. //关闭触发器开关
    60. transform.GetComponent().enabled=false;
    61. //把玩家的手和道具绑定在一起(设置右手位置物体,为道具的父物体)
    62. transform.SetParent(rHandItemPos);
    63. }
    64. //丢弃道具
    65. void DisCardItem()
    66. {
    67. if(rHandIsHasItem)
    68. {
    69. rHandIsHasItem = false;
    70. //关闭刚体的忽略物理学运算开关
    71. transform.GetComponent().isKinematic = false;
    72. //加力
    73. transform.GetComponent().AddForce(Vector3.forward*2000f);
    74. //打开碰撞器开关
    75. transform.GetComponent().enabled = true;
    76. //打开触发器开关
    77. transform.GetComponent().enabled = true;
    78. //把玩家的手和道具解绑
    79. transform.SetParent(null);
    80. }
    81. }
    82. }

    视角的移动

     CameraMove脚本(绑定在摄像机身上)

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. ///
    5. /// 第三人称摄像机简单版
    6. ///
    7. public class CameraMove : MonoBehaviour
    8. {
    9. public Transform target;//摄像机的跟随目标
    10. public float distance = 8.0f;//摄像机与目标之间的距离
    11. private float x, y, z;
    12. private float xSpeed = 250.0f;
    13. private float ySpeed = 120.0f;
    14. //限制上下移动角度
    15. public float yMinlimit = -45.0f;
    16. public float yMaxlimit = 45.0f;
    17. /* private void Awake()
    18. {
    19. //注册场景加载完毕事件
    20. EventCenter.AddListener(EventType.SceneLoadComplete, SetTarget);
    21. }*/
    22. private void SetTarget()
    23. {
    24. //将标签为Player的物体设置为跟踪目标
    25. Transform player = GameObject.FindGameObjectWithTag("Player").transform;
    26. if (player != null && target == null)
    27. target = player;
    28. }
    29. private void Start()
    30. {
    31. Vector3 angles = transform.eulerAngles;//获取摄像机的当前角度
    32. x = angles.x;
    33. y = angles.y;
    34. z = -distance;
    35. GoRight();
    36. }
    37. private void LateUpdate()
    38. {
    39. float temp = Input.GetAxis("Mouse ScrollWheel");//获取滚轮数值
    40. if (target != null)
    41. {
    42. if (Input.GetMouseButton(0))
    43. {
    44. x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    45. y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    46. }
    47. /*
    48. else if (Input.GetMouseButton(1))
    49. {
    50. x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
    51. y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    52. //影响玩家的Y轴旋转角度
    53. target.rotation = Quaternion.Euler(target.rotation.x,x,target.rotation.z);
    54. }
    55. */
    56. }
    57. //钳制上下移动的角度
    58. y = ClampAngle(y,yMinlimit,yMaxlimit);
    59. z += temp * 100f * 0.02f;//数值按照自己喜好设定
    60. z = Mathf.Clamp(z,-20f,-3.0f);//距离限制,最远是距离玩家20米,最近是3米
    61. GoRight();//作用于摄像机
    62. }
    63. float ClampAngle(float angle,float min,float max)
    64. {
    65. if (angle < -360)
    66. angle += 360;
    67. if (angle > 360)
    68. angle -= 360;
    69. return Mathf.Clamp(angle,min,max);
    70. }
    71. //摄像机控制位置及角度的核心方法
    72. void GoRight()
    73. {
    74. if (target == null)
    75. return;
    76. Quaternion rotation = Quaternion.Euler(y,x,0);//摄像机角度
    77. Vector3 position = rotation * new Vector3(0.0f,0.0f,z)+target.position;
    78. transform.position = position;//摄像机位置
    79. transform.rotation = rotation;//摄像机角度
    80. }
    81. }

    怪物的按路径移动,攻击,闲置状态

    MonsterAI脚本(绑定在怪物身上)

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using static UnityEditor.FilePathAttribute;
    5. public enum MonstorAIState
    6. {
    7. idle,//闲置状态
    8. Patrol,//巡逻
    9. ChasePlayer,//追击玩家
    10. AttackPlayer,//攻击玩家
    11. //自己添加其他状态
    12. }
    13. public class MonsterAI : MonoBehaviour
    14. {
    15. public float speed = 2f;//移动速度
    16. public Transform[] wayPointArr;//路径点数组
    17. public Transform pathObj;//路径点父物体
    18. //当前的路径点下标
    19. public int currentWaypointIndex = 0;
    20. private Animator _animator;//动画器
    21. public MonstorAIState monsterCurrentState=0;//怪物当前状态
    22. public MonstorAIState monsterOldState=0;
    23. private Transform playerObj;//玩家物体
    24. public bool isAlive=true;//丧尸是否活着
    25. public bool isFindPlayer = false;//是否发现玩家
    26. // Start is called before the first frame update
    27. void Start()
    28. {
    29. //在场景里通过标签查找玩家物体
    30. playerObj = GameObject.FindGameObjectWithTag("Player").transform;
    31. //判断玩家是否已经正确找到
    32. if(playerObj==null)
    33. {
    34. Debug.LogError("没有找到玩家物体,请查看玩家标签是否正确设置为Player");
    35. }
    36. _animator = GetComponent();//获取动画器组件引用
    37. //自动搜索场景中的路径点加载到路径点数组中
    38. if (pathObj != null)
    39. {
    40. //数组开辟内存
    41. wayPointArr = new Transform[pathObj.childCount];
    42. for (int i = 0; i < pathObj.childCount; i++)
    43. {
    44. wayPointArr[i] = pathObj.GetChild(i).transform;
    45. }
    46. }
    47. else
    48. {
    49. Debug.LogError("路径点父物体没有拽入参数栏");
    50. }
    51. //开启协程
    52. StartCoroutine(IsFindPlayer(1f,25f));
    53. }
    54. // Update is called once per frame
    55. void Update()
    56. {
    57. //如果丧失已经死亡,则不郧西下面代码
    58. if (!isAlive)
    59. return;
    60. switch (monsterCurrentState)
    61. {
    62. case MonstorAIState.idle:
    63. Idle();
    64. break;
    65. case MonstorAIState.Patrol://巡逻状态
    66. Patrol();
    67. break;
    68. case MonstorAIState.ChasePlayer://追击玩家
    69. ChasePlayer();
    70. break;
    71. case MonstorAIState.AttackPlayer://追击玩家
    72. AttackPlayer();
    73. break;
    74. }
    75. }
    76. void Patrol()//巡逻状态
    77. {
    78. speed = 0.5f;
    79. _animator.SetFloat("moveSpeed",speed);
    80. //计算怪物与目标点之间的角度 并进行方向修正
    81. Vector3 direction = wayPointArr[currentWaypointIndex].position - transform.position;
    82. //计算旋转角度并旋转
    83. transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), 0.1f);
    84. if (direction.sqrMagnitude < 0.02f)
    85. {
    86. if (currentWaypointIndex++ == wayPointArr.Length - 1)
    87. {
    88. currentWaypointIndex = 0;
    89. }
    90. }
    91. //一直前进
    92. transform.Translate(Vector3.forward * Time.deltaTime * speed);
    93. //播放动画
    94. _animator.SetFloat("moveSpeed", speed);
    95. }
    96. //闲置
    97. void Idle()
    98. {
    99. speed = 0;
    100. _animator.SetFloat("moveSpeed",speed);
    101. }
    102. //追击玩家方法
    103. void ChasePlayer()
    104. {
    105. speed = 0.8f;
    106. _animator.SetFloat("moveSpeed", speed);
    107. //面向玩家
    108. //计算与玩家的角度
    109. Vector3 direction = playerObj.position - transform.position;
    110. //计算旋转角度并旋转
    111. transform.rotation = Quaternion.Slerp(transform.rotation,
    112. Quaternion.LookRotation(direction),
    113. 0.1f);
    114. //一直前进
    115. transform.Translate(Vector3.forward * Time.deltaTime * speed);
    116. //播放动画
    117. _animator.SetFloat("moveSpeed", speed);
    118. //如果玩家与怪物之间的距离大于设定的N米,则返回旧状态
    119. if(direction.sqrMagnitude>10f*10f)
    120. {
    121. monsterCurrentState = monsterOldState;
    122. isFindPlayer = false;//玩家追丢了,重置
    123. }
    124. //查找玩家的协程有没有开启
    125. //如果玩家与怪物之间的距离小于设定的距离,则进入到攻击状态
    126. print(direction.sqrMagnitude);
    127. if(direction.sqrMagnitude<0.4f)
    128. {
    129. monsterCurrentState=MonstorAIState.AttackPlayer;//攻击玩家
    130. }
    131. }
    132. //通过与玩家距离来判断是否发现玩家
    133. IEnumerator IsFindPlayer(float intervalTime, float discoveryDistance)
    134. {
    135. while (isAlive)
    136. {
    137. if (!isFindPlayer && playerObj != null)
    138. {//计算与玩家的距离
    139. Vector3 direction = playerObj.position - transform.position;
    140. if (direction.sqrMagnitude < discoveryDistance*discoveryDistance)
    141. {
    142. //发现玩家
    143. print("怪物已经发现玩家!");
    144. isFindPlayer = true;
    145. //记录旧状态
    146. monsterOldState = monsterCurrentState;
    147. //将当前的怪物状态设置为追击玩家状态
    148. monsterCurrentState = MonstorAIState.ChasePlayer;
    149. }
    150. /* else
    151. {
    152. //将当前的怪物状态设置为闲置状态
    153. monsterCurrentState = MonstorAIState.idle;
    154. }*/
    155. }
    156. yield return new WaitForSeconds(intervalTime);
    157. }
    158. }
    159. void AttackPlayer()
    160. {
    161. speed = 0;
    162. _animator.SetFloat("moveSpeed", speed);
    163. _animator.SetTrigger("Attack");//播放攻击玩家动画
    164. //计算与玩家的距离
    165. Vector3 direction = playerObj.position - transform.position;
    166. if(direction.sqrMagnitude>0.4f)
    167. {
    168. monsterCurrentState = MonstorAIState.ChasePlayer;
    169. }
    170. }
    171. }

    在距离小于3f时,调用伤害方法

    MonsterAnimationEvent脚本(绑定在怪物身上)

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.VisualScripting;
    4. using UnityEngine;
    5. public class MonsterAnimationEvent : MonoBehaviour
    6. {
    7. public GameObject playerObj;
    8. private void Start()
    9. {
    10. if (playerObj == null)
    11. {
    12. playerObj = GameObject.FindGameObjectWithTag("Player");
    13. }
    14. }
    15. public void AttackPlayer(float damage)
    16. {
    17. if (playerObj != null)
    18. {
    19. float distance = Vector3.Distance(playerObj.transform.position, transform.position);
    20. // 打印距离
    21. Debug.Log(distance);
    22. if (distance < 3f)
    23. {
    24. playerObj.GetComponent().TakeDamage(damage);
    25. }
    26. }
    27. }
    28. }

  • 相关阅读:
    【canvas】了解canvas,并实现会议预定记录钟表盘、页面水印
    【HTTPS】通过OpenSSL在Windows上生成Https证书
    从零搭建Vue项目
    2022R2移动式压力容器充装考试试题模拟考试平台操作
    HBuilder(uniapp) 配置android模拟器
    在数据库插入万条数据,比普通插入提升百倍速度
    【ATT&CK】基于ATT&CK识别网络钓鱼攻防战法
    西门子低代码首席执行官对现代数字化转型的一些看法
    初探基因组组装——生信原理第四次实验报告
    程序运行时增加语音提示
  • 原文地址:https://blog.csdn.net/m0_74289471/article/details/139458798