RPG人物操作

本文介绍了一款Unity 3D游戏中的玩家输入处理和角色控制脚本。通过键盘和鼠标输入,实现了摄像机旋转和人物移动,使用了平滑移动和椭圆映射法来优化移动效果。同时,详细展示了角色的动画控制,包括攻击、跳跃、技能释放等行为,以及受伤害后的状态更新。此外,还涉及到了UI元素如血条的实时同步和动画事件的触发机制。
摘要由CSDN通过智能技术生成
人物按键脚本
现设置绑定一些按键,让鼠标的旋转控制摄像机,否则键盘控制摄像机,然后通过两个二目运算符得到前后左右的值,然后将其进行平滑移动,当开关关闭的时候,目标值为零,借助椭圆映射法,将二维向量传入其中,移动的距离和移动的方向都可以求出来

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerInput : MonoBehaviour
{
    [Header("自定义设置的按键")]
    public string keyA;
    public string keyB;
    public string keyC;
    public string keyD;
    public string keyE;
    public string keyF;
    public string keyG;
    //上下左右调整摄像机转动
    [Header("人物移动的按键")]
    public string keyJRight;
    public string keyJUp;
    public string keyJDown;
    public string keyJLeft;
    //上下左右调整人物转动
    [Header("鼠标转动的按键")]
    public string keyUp;
    public string keyDown;
    public string keyRight;
    public string keyLeft;
    //摄像机上下转
    public float Jup;
    //摄像机左右转
    public float Jright;
    //鼠标转动速度
    public float mouseSensitiivity;
    //移动的距离
    public float Dmag;
    //方向
    public Vector3 Dvec;
    //垂直方向目标的值
    public float targetDup;
    //水平方向目标的值
    public float targetDright;
    //上下移动
    public float Dup;
    //左右移动
    public float Dright;
    //垂直方向上的速度
    public float velocityDup;
    //水平方向上的速度
    public float velocityDright;
    //开局不锁定位移
    private bool inputEnabled=true;
    //是否跑步
    public bool run;
    //是否跳
    public bool jump;
    
    

    private void Update()
    {
        //鼠标旋转控制摄像机
        if (Input.GetMouseButton(1))
        {
            Jup = Input.GetAxis("Mouse Y") * mouseSensitiivity;
            Jright = Input.GetAxis("Mouse X") * mouseSensitiivity;
        }
        //键盘转控制摄像机
        else
        {
            Jup = (Input.GetKey(keyJUp) ? 1.0f : 0) - (Input.GetKey(keyJDown) ? 1.0f : 0);
            Jright = (Input.GetKey(keyJRight) ? 1.0f : 0) - (Input.GetKey(keyJLeft) ? 1.0f : 0);
        }
        //两个二目运算符相运算得到目标的值
        targetDup = (Input.GetKey(keyUp) ? 1.0f : 0) - (Input.GetKey(keyDown) ? 1.0f : 0);
        targetDright = (Input.GetKey(keyRight) ? 1.0f : 0) - (Input.GetKey(keyLeft) ? 1.0f : 0);
        //平滑处理上下的移动
        Dup = Mathf.SmoothDamp(Dup, targetDup, ref velocityDup, 0.1f);
        //平滑处理左右移动
        Dright = Mathf.SmoothDamp(Dright, targetDright, ref velocityDright, 0.1f);
        //如果开关关闭
        if (inputEnabled==false)
        {
            //将目标值全部归零
            targetDup = 0;
            targetDright = 0;
        }
        
        //将此二维向量传入椭圆映射方法中
        Vector2 tempDAixs = SquareToCircle(new Vector2(Dright, Dup));
        //得到两个新的长度
        float Dright2 = tempDAixs.x;
        float Dup2 = tempDAixs.y;
        //移动的距离
        Dmag = Mathf.Sqrt(Dright2 * Dright2+ Dup2 * Dup2);
        //移动的方向
        Dvec = Dright2 * transform.right + Dup2 * transform.forward;
        //跑步开关
        run = Input.GetKey(keyA);
        jump = Input.GetKeyDown(keyB);
        
    }
    /// <summary>
    /// 椭圆映射法
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    protected Vector2 SquareToCircle(Vector2 input)
    {
        //设一个二维向量
        Vector2 output=Vector2.zero;
        //将xy进行椭圆映射运算
        output.x = input.x * Mathf.Sqrt(1 - (input.y * input.y) / 2.0f);
        output.y = input.y * Mathf.Sqrt(1 - (input.x * input.x) / 2.0f);
        return output;
    }
}
移动控制脚本
当人物的速度小于0.5时,执行随机动作,然后进行技能的释放,当按技能键并且不在cd中 释放技能,当抬起按键的时候,技能返回cd中,当按下左shift执行动画跑,并且用二目运算符来确定跑了的话就加大速度,判断跳的动画进行选择,人物移动的向量大于0.1时,人物朝向为转向向量,移动的方向向量为前面所算出的向量,进行移动,
站立时候的动作,定义0-3之间当时间大于20时 为num ,否则为-1,然后执行动画,当timer大于27的时候返回零,反之则为timer
using System;
using System.Collections;
using System.Collections.Generic;
using UnityChan;
using UnityEngine;
using UnityEngine.TextCore;
using Random = UnityEngine.Random;

public class ActorController : MonoBehaviour
{
    //人物模型
    public GameObject model;
    //playerinput类    
    public PlayerInput pi;
    //行走速度
    public float walkSpeed;
    //跑步速度
    public float runSpeed;
    //动画
    private Animator _animator;
    //移动的向量
    private Vector3 planarVec;
    //人物刚体
    private Rigidbody rig;
    //上跳乘数
    public float jumpVelocity;
    //翻滚乘数
    public float rollVelocity;
    //冲量向量
    public Vector3 thrustVec;
    //相机脚本
    public CamController camcon;
    //锁死位移
    private bool lockPlanar;
    //是否能攻击
    private bool canAttack;
    //轨道方向
    private bool trackDirction;
    //刚体
    public CapsuleCollider col;
    [Header("----------摩擦材质------------")] 
    public PhysicMaterial frictionOne;
    public PhysicMaterial frictionZero;
    //wait动画时间
    private float timer;
    //第三段攻击动画位移
    private Vector3 deltaPos;
    private float lerpTarget;
    private float lerpTarget1;
    private AudioSource _source;
    private HeroProperty _heroProperty;
    public CdShow skillShow;
    

    private void Awake()
    {
        _animator = model.GetComponent<Animator>();
        pi = GetComponent<PlayerInput>();
        rig = GetComponent<Rigidbody>();
        col = GetComponent<CapsuleCollider>();
        _source = GetComponent<AudioSource>();
        _heroProperty = GameObject.FindWithTag("Property").GetComponent<HeroProperty>();
        
    }

    
    
    private void Update()
    {
        timer += Time.deltaTime;
        if (rig.velocity.magnitude<0.1f)
        {
            wait();
        }
        //skill1
        if (Input.GetKeyDown(KeyCode.J))
        {
            _animator.SetTrigger("attack1");
        }
        //skill2
        if (Input.GetKeyDown(pi.keyC)&&skillShow.cdskill2==false)
        {
            _animator.SetTrigger("attack2");
        }
        if (Input.GetKeyUp(pi.keyC))
        {
            skillShow.cdskill2=true;
        }
        //skill3
        if (Input.GetKeyDown(pi.keyD)&&skillShow.cdskill3==false)
        {
            _animator.SetTrigger("attack3");
        }
        if (Input.GetKeyUp(pi.keyD))
        {
            skillShow.cdskill3=true;
        }
        //skill4
        if (Input.GetKeyDown(pi.keyE)&&skillShow.cdskill4==false)
        {
            _animator.SetTrigger("attack4");
        }
        if (Input.GetKeyUp(pi.keyE))
        {
            skillShow.cdskill4=true;
        }

        
        
        if (Input.GetKey(KeyCode.LeftShift))
        {
            if (timer>10)
            {
                if (!_source.isPlaying)
                {
                    _source.Play();
                }

                timer = 0;
            }
        }
        if (Input.GetKeyUp(KeyCode.LeftShift))
        {
            _source.Stop();
        }
        //播放动画 里面用了一个线性插值运算
        _animator.SetFloat("forward", pi.Dmag*Mathf.Lerp(_animator.GetFloat("forward"),
                                          pi.run ? 2.0f : 1.0f,0.5f));
        if (pi.jump)
        {
            if (rig.velocity.magnitude<0.5f)
            {
                _animator.SetBool("jump1",false);
            }
            else
            {
                _animator.SetBool("jump1",true);
            }
            _animator.SetTrigger("jump");
        }
        //移动的向量大于0.1
        if (pi.Dmag>0.1f)
        {
            //人物的朝向
            model.transform.forward = Vector3.Slerp(model.transform.forward, pi.Dvec, 0.3f);
        }
        
        //移动的方向向量
        planarVec = pi.Dmag * model.transform.forward*walkSpeed*(pi.run?runSpeed:1.0f);
    }
    private void FixedUpdate()
    {
         //移动
         rig.velocity=new Vector3(planarVec.x,rig.velocity.y,planarVec.z);
         
        //冲量归零
         thrustVec=Vector3.zero;
         
    }
    //站立动作
    private void wait()
    {
        int num = Random.Range(0, 3);
        num = timer > 20 ? num : -1;
        _animator.SetInteger("AnimatorNum",num);
        timer = timer > 27 ? 0 : timer;
    }
}
动画返回的时候清除tigger信号

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FsmClearSignels : StateMachineBehaviour
{
    //清除进入前的数据
    public string[] clearAtEnter;
    public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        foreach (var signal in clearAtEnter)
        {
            //清除
            animator.ResetTrigger(signal);
        }
    }
}

进入动画的时候通知给母件的信息
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FsmOnEnter : StateMachineBehaviour
{
    public string[] OnEnterMessages;
    public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        foreach (var msg in OnEnterMessages)
        {
            //通知母组件给其信息
            animator.gameObject.SendMessageUpwards(msg);
            
        } 
    }
}
人物属性 开局的时候在面板显示 时刻再update中更新
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;

public class HeroProperty : MonoBehaviour
{
    public int hp;
    public int mp;
    public int attack;
    public int speed;
    public int money;
    public Text _texthp;
    public Text _textmp;
    public Text _textspeed;
    public Text _textattack;
    public Text _textmoney;
    public int allHp = 200;
    public int allMp = 100;
    public int allNum = 20;

    private void Start()
    {
        _texthp.text = hp.ToString();
        _textmp.text = mp.ToString();
        _textspeed.text = speed.ToString();
        _textattack.text = attack.ToString();
        _textmoney.text = money.ToString();

    }

    private void Update()
    {
        _texthp.text = allHp.ToString();
        _textmp.text = allMp.ToString();
        _textspeed.text = speed.ToString();
        _textattack.text = attack.ToString();
        _textmoney.text = money.ToString();
    }

}
人物受伤害,当人物血小于零时,从新回到该场景,当人物触发敌人的刀光,后面的血条跟着前面的血条走,加血的时候前面跟着后面走

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;

public class PlayerDamage : MonoBehaviour
{
    private SceneAgain _sceneAgain;
    private HeroProperty _heroProperty;
    public int damage;
    public Scrollbar scrollbarHp;
    public Scrollbar scrollbarMp;
    private Image _imageHp;
    private Image _imageMp;
    private Text _textCurrentHp;
    private Text _textOlderHp;
    private Text _textCurrentMp;
    private Text _textOlderMp;
    private Animator _animator;
    public bool onOffHp;
    public bool onOffMp;
    private void Start()
    {
        _heroProperty = GameObject.FindWithTag("Property").GetComponent<HeroProperty>();
        _animator = transform.GetChild(0).GetComponent<Animator>();
        _imageHp = scrollbarHp.transform.GetChild(0).GetChild(0).GetComponent<Image>();
        _textCurrentHp = scrollbarHp.transform.GetChild(1).GetComponent<Text>();
        _textOlderHp = scrollbarHp.transform.GetChild(2).GetComponent<Text>();
        _imageMp = scrollbarMp.transform.GetChild(0).GetChild(0).GetComponent<Image>();
        _textCurrentMp = scrollbarMp.transform.GetChild(1).GetComponent<Text>();
        _textOlderMp = scrollbarMp.transform.GetChild(2).GetComponent<Text>();
        _sceneAgain = GameObject.Find("CanvasScene").transform.GetChild(0).GetChild(5).GetComponent<SceneAgain>();

         _textCurrentHp.text = _heroProperty.hp.ToString();
         _textCurrentMp.text = _heroProperty.mp.ToString();
        _textOlderHp.text = "/" + _heroProperty._texthp.text;
        _textOlderMp.text = "/" + _heroProperty._textmp.text;
    }
    
    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("EnemySlash"))
        {
            _heroProperty.hp -= damage;
            onOffHp = false;
            _animator.SetTrigger("damage");
        }
    }

    
    private void Update()
    {
        
        if (_heroProperty.hp<0)
        {
            _animator.SetTrigger("die");
            Destroy(gameObject,2);
            _sceneAgain.EndScene();
        }

        if (onOffHp)
        {
            _imageHp.fillAmount = Mathf.Lerp(_imageHp.fillAmount,
                (float) _heroProperty.hp / int.Parse(_heroProperty._texthp.text), Time.deltaTime * 10);

            scrollbarHp.size = Mathf.Lerp(scrollbarHp.size, _imageHp.fillAmount, Time.deltaTime * 5);
        }
        else
        {
            scrollbarHp.size = Mathf.Lerp(scrollbarHp.size,
                (float) _heroProperty.hp / int.Parse(_heroProperty._texthp.text), Time.deltaTime * 10);
            
            _imageHp.fillAmount = Mathf.Lerp(_imageHp.fillAmount,scrollbarHp.size, Time.deltaTime * 5);
        }

        if (onOffMp)
        {
            _imageMp.fillAmount = Mathf.Lerp(_imageMp.fillAmount,(float) _heroProperty.mp / int.Parse(_heroProperty._textmp.text), Time.deltaTime * 10);

            scrollbarMp.size = Mathf.Lerp(scrollbarMp.size, _imageMp.fillAmount , Time.deltaTime * 5);
        }
        
        else
        {
           
            scrollbarMp.size = Mathf.Lerp(scrollbarMp.size, (float) _heroProperty.mp / int.Parse(_heroProperty._textmp.text), Time.deltaTime * 10);
            
            _imageMp.fillAmount = Mathf.Lerp(_imageMp.fillAmount, scrollbarMp.size, Time.deltaTime * 5);
        }
            
        
        _textCurrentHp.text = Mathf.RoundToInt(scrollbarHp.size * int.Parse(_heroProperty._texthp.text)).ToString();
        _textCurrentMp.text = Mathf.RoundToInt(scrollbarMp.size * int.Parse(_heroProperty._textmp.text)).ToString();
        
        
        
        _textOlderHp.text = "/" + _heroProperty._texthp.text;
        _textOlderMp.text = "/" + _heroProperty._textmp.text;
    }
}

事件函数,写在模型上,执行动画事件
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestEvent : MonoBehaviour
{ 
    private Transform _model;
    private HeroProperty _heroProperty;
    private CdShow _cdShow;

    private void Start()
    { 
        _model = GameObject.FindWithTag("Player").transform.GetChild(0).transform;
        _heroProperty = GameObject.FindWithTag("Property").GetComponent<HeroProperty>();
        _cdShow = GameObject.Find("CanvasScene").transform.GetChild(0).GetChild(0).GetComponent<CdShow>();
    }

    
    
    public void Audio0(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }
    public void Audio1(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }
    public void Audio2(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }
    public void Audio3(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }

    public void Attack21(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }
    public void Attack31(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }
    public void Attack41(AudioClip audio)
    {
        AudioSource.PlayClipAtPoint(audio,transform.position);
    }
    
    
    public void Attack1(GameObject _obj)
    {
        GameObject obj = Instantiate(_obj,
            _model.transform.position + _model.forward.normalized,
            _obj.transform.rotation);
        obj.GetComponent<Rigidbody>().velocity = _model.forward * 0.5f;
        Destroy(obj,3f);
    }
    public void Attack2(GameObject _obj)
    {
        _heroProperty.mp -= _cdShow.needMp2;
        GameObject obj = Instantiate(_obj,
            _model.transform.position + _model.forward.normalized + _model.up.normalized, 
            _obj.transform.rotation,_model);
        Destroy(obj,0.5f);
    }
    public void Attack3(GameObject _obj)
    {
        _heroProperty.mp -= _cdShow.needMp3;

        GameObject obj = Instantiate(_obj, _model.transform.position, _obj.transform.rotation,_model);
        Destroy(obj,3f);
    }
    public void Attack4(GameObject _obj)
    {
        _heroProperty.mp -= _cdShow.needMp4;

        GameObject obj = Instantiate(_obj, _model.transform.position , _model.rotation);
        obj.GetComponent<Rigidbody>().velocity = _model.forward*5f;
        Destroy(obj,3f);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值