个人课设---玩家血条(包括攻击掉血,复活重生功能)+怪物攻击+玩家的拾取

血条UI操作

渲染模式改为世界空间

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

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

为了使血条填满,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<Rigidbody>().isKinematic = true;
        //关闭碰撞器开关
        transform.GetComponent<BoxCollider>().enabled=false;
        //关闭触发器开关
        transform.GetComponent<SphereCollider>().enabled=false;

        //把玩家的手和道具绑定在一起(设置右手位置物体,为道具的父物体)
        transform.SetParent(rHandItemPos);

    }
    //丢弃道具
    void DisCardItem()
    {
        if(rHandIsHasItem)
        {
            rHandIsHasItem = false;
            //关闭刚体的忽略物理学运算开关
            transform.GetComponent<Rigidbody>().isKinematic = false;
            //加力
            transform.GetComponent<Rigidbody>().AddForce(Vector3.forward*2000f);
            //打开碰撞器开关
            transform.GetComponent<BoxCollider>().enabled = true;
            //打开触发器开关
            transform.GetComponent<SphereCollider>().enabled = true;

            //把玩家的手和道具解绑
            transform.SetParent(null);
        }

       
    }
}

视角的移动

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

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 第三人称摄像机简单版
/// </summary>
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<Animator>();//获取动画器组件引用

            //自动搜索场景中的路径点加载到路径点数组中
            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<PlayerHealth>().TakeDamage(damage);
            }
        }
    }
}

  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值