Unity3D效果实现:主角篇

我们来实现RPG游戏中第三人称的主角功能实现

1.摄像机

实现效果:摄像机跟随主角转动而转动,位置处于主角身后

  • 首先需要创建一个空物体,其位置和主角位置一样,随后添加一个摄像机作为其子物体,并将其挪至主角身后。
  • 随后挂上该脚本
sing System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraControl : MonoBehaviour
{
    private Transform player;
    private Vector3 dir;
    // Start is called before the first frame update
    void Start()
    {
        player = GameObject.FindWithTag("Player").transform;
        dir = player.transform.position - transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        transform.position = player.transform.position - dir;
        //如果指针为呼出状态,则不做任何事
        if (Cursor.lockState == CursorLockMode.None)
        {
            Debug.Log("do nothing");
            return;
        }
        float mouseX = Input.GetAxis("Mouse X");
        transform.Rotate(Vector3.up, mouseX * 90 * Time.deltaTime);
    }
}

2.人物状态

  • 人物包含攻击,默认,受伤,奔跑等状态,需要一个状态管理类来管理
  • 人物的攻击需要使用动画和特效来完成,在动画中添加关键帧事件可以调用函数
  • 人物包含默认的属性如生命值,攻击力等
  • 脚本代码如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum PlayerState
{
   idle,
   run,
   die,
   attack,
}

public class PlayerControl : MonoBehaviour
{
    private PlayerState state = PlayerState.idle;
    private Rigidbody rbody;
    private Animator animator;
    public int MaxHp = 100;
    public int hp = 100;
    //特效数组
    private List<Transform> fxList;
    // Start is called before the first frame update
    void Start()
    {
        animator = GetComponent<Animator>();
        rbody = GetComponent<Rigidbody>();
        Cursor.lockState = CursorLockMode.Locked;
        fxList = new List<Transform>();
    }

    // Update is called once per frame
    void Update()
    {
        //主角与摄像机同步旋转
        switch(state)
        {
            case PlayerState.idle:
                Rotate();
                Move();
                Attack();
                animator.SetBool("Run", false);
                break;
            case PlayerState.run:
                Rotate();
                Move();
                Attack();
                animator.SetBool("Run", true);
                break;
            case PlayerState.die:
                break;
            case PlayerState.attack:
                break;
        }
        if(Input.GetKeyDown(KeyCode.LeftAlt))
        {
            Cursor.lockState = Cursor.lockState == CursorLockMode.Locked ? CursorLockMode.None : CursorLockMode.Locked;
        }
        if(Cursor.lockState==CursorLockMode.None)
        {
            return;
        }
        //要删除的特效
        Transform fx = null;
        foreach(Transform trans in fxList)
        {
            //特效移动
            trans.Translate(Vector3.forward * 20 * Time.deltaTime);
            Collider[] colliders = Physics.OverlapSphere(transform.position, 1f);
            foreach(Collider collider in colliders)
            {
                if(collider.tag=="Enemy")
                {
                    collider.GetComponent<EnemyControl>().GetDamage(20);
                    //待删除的火焰特效
                    fx = trans;
                    //爆炸特效
                    //加载特效预制件
                    GameObject fxPre = Resources.Load<GameObject>("Explosion");
                    //实例化特效
                    GameObject go = Instantiate(fxPre, collider.transform.position, collider.transform.rotation);
                    Destroy(go, 2f);
                    break;
                }
            }
        }
        if(fx!=null)
        {
            fxList.Remove(fx);
        }
    }
    
    public void Rotate()
    {
        transform.rotation = Camera.main.transform.parent.rotation;
    }

    void Move()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        {
            rbody.velocity = transform.forward * vertical * 4;
            rbody.velocity += transform.right * horizontal * 2;
            state = PlayerState.run;
        }
        else
        {
            state = PlayerState.idle;
        }
    }
    void Attack()
    {
        if(Input.GetKeyDown(KeyCode.Q))
        {
            animator.SetTrigger("Attack");
            state = PlayerState.attack;
        }

    }

    void AttackEnd()
    {
        state = PlayerState.idle;
    }

    public void GetDamage(int damage)
    {
        hp -= damage;
        if(hp<0)
        {
            state = PlayerState.die;
            animator.SetTrigger("Die");
        }    
    }

    public void Revive(Vector3 position)
    {
        if(state==PlayerState.die)
        {
            animator.SetTrigger("Revive");
            state = PlayerState.idle;
            transform.position = position;
        }
    }

    void Damage(int damage)
    {
        Collider[] colliders = Physics.OverlapSphere(transform.position, 3f);
        foreach (Collider collider in colliders)
        {
            //判定是敌人并在60度的攻击范围内
            if (collider.tag == "Enemy" && Vector3.Angle(collider.transform.
                position - transform.position, transform.forward)<60)
            {
                collider.GetComponent<EnemyControl>().GetDamage(damage);
            }
         } 
    }

    Transform FX(string name,float desTime)
    {
        GameObject fxPre = Resources.Load<GameObject>(name);
        //实例化特效
        GameObject go = Instantiate(fxPre, transform.position, transform.rotation);
        //删除特效物体
        Destroy(go, desTime);
        return go.transform;
    }

    void Attack1_1()
    {
        Damage(20);
        FX("fx_hr_authur_attack_01_1", 0.5f);
    }

    void ClearFXList()
    {
        fxList.Clear();
    }
}
posted @ 2021-11-29 19:53  不进育碧不改名  阅读(177)  评论(0编辑  收藏  举报