美文网首页Android游戏
从零开始的RPG制作(2.1-人物控制)

从零开始的RPG制作(2.1-人物控制)

作者: 小蜻蜓队长 | 来源:发表于2019-04-25 14:44 被阅读55次

    在上一张内容中我们设计了基础结构,现在我们来开始实现人物控制。首先我们去找一个漂亮的小姐姐来做我们的模特。


    小姐姐照片

    我们就用这个小姐姐了。(非商业,大家可以去网上找找 Eri,这里就不贴出链接了~)

    i场景

    接着我们在场景中拉出几块cube 和 一个plane ,把小姐姐放进去。

    1.创建Update控制器

    我们不妨先思考一下,角色控制器肯定是需要时序每一帧都接收用户输入的信号的,那么自然而然的就会想到在update里面进行操作,然后就在角色脚本的update的函数里开始写,这种做法太过粗旷,我们的游戏,只需要一组Update就行了,其他需要Update的东西放入那里面就行,那具体如果做了,下面贴码。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class UpdateManges:MonoBehaviour {
        public delegate void UpdateManage();
        static event UpdateManage playerEventList_LateUpdate;//人物事件需要放入lateUpdate处理的。
        static event UpdateManage playerEventList_FixUpdate;//人物事件需要放入FixUpdate处理的。
        static event UpdateManage playerEventList_Update;//人物事件需要放入Update处理的。
        #region 事件的删除与添加
        public static void add_playerEventList_Late(UpdateManage updatemanage) {
            if (updatemanage != null)
                playerEventList_LateUpdate += updatemanage;
        }
        public static void sub_playerEventList_Late(UpdateManage updatemanage) {
            if (updatemanage != null)
                playerEventList_LateUpdate -= updatemanage;
        }
    
        public static void add_playerEventList_Fix(UpdateManage updatemanage) {
            if (updatemanage != null)
                playerEventList_FixUpdate += updatemanage;
        }
        public static void sub_playerEventList_Fix(UpdateManage updatemanage) {
            if (updatemanage != null)
                playerEventList_FixUpdate -= updatemanage;
        }
    
        public static void add_playerEventList_(UpdateManage updatemanage) {
            if (updatemanage != null)
                playerEventList_Update += updatemanage;
        }
        public static void sub_playerEventList_(UpdateManage updatemanage) {
            if (updatemanage != null)
                playerEventList_Update -= updatemanage;
        }
        #endregion
        private void Update() {
            if (playerEventList_Update != null) {
                playerEventList_Update();
            }
        }
    
    
        private void LateUpdate() {
            if (playerEventList_LateUpdate != null) {
                playerEventList_LateUpdate();
            }
        }
    
        private void FixedUpdate() {
            if (playerEventList_FixUpdate != null) {
                playerEventList_FixUpdate();
            }
        }
    
    }
    

    应该还是比较清晰的,外部就通过这几个静态函数调用就可以,然后我们把我们的码子丢道一个GameObject,取名为UpdateManage。

    2.小姐姐的基础配置。

    首先我们创建一个空物体称之为Player,将PlayerTestView丢在这个Player上,接着将小姐姐放入这个Player,将小姐姐身上挂着的东西全部remove掉,接着我们在Player挂上一个Capsule Collider 和 一个 Rigidbody。

    当这步配置结束之后,我们创建一个 Animator命名为 playerAnim。然后将小姐姐的骨骼绑定在上面。


    配置

    接着配置Animator。
    我们在playerAnim中创建一个1D混合树,用于混合小姐姐静默状态,走路状态,跑步状态。


    配置如图

    接着设置一个walk的变量来作为1D混合书的混合参数。


    配置如图

    接着我们就要回到角色控制最为关键的两个类用于显示的PlayerTestView和用于操作的PlayerTestMediator。

    3.创建输入信号接受函数,PlayerTestMediator中的关键函数keyController。

    using strange.extensions.mediation.impl;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PlayerTestMediator:Mediator {
    
        // Use this for initialization
        //test
        float up = 0;
        float right = 0;
        float upVelocity = 0;
        float rightVelocity = 0;
        Vector3 vec;
        [Inject]
        public PlayerTestView playerView { get; set; }
    
        public override void OnRegister() {//绑定成功之后会调用这个API
            Debug.Log("OnRegister");
            playerView.init();
            UpdateManges.add_playerEventList_(keyController);
        }
        public override void OnRemove() {//接触绑定之后调用这个API
            Debug.Log("OnRemove");
            UpdateManges.sub_playerEventList_(keyController);
    
        }
        bool run = false;
        bool jump = false;
        void keyController() {
            ///用wasd来控制前进与否
            float targetup = (Input.GetKey("w") ? 1 : 0) - (Input.GetKey("s") ? 1 : 0);
            float targetright = (Input.GetKey("d") ? 1 : 0) - (Input.GetKey("a") ? 1 : 0);
            up = Mathf.Lerp(up, targetup,0.6f);
            right = Mathf.Lerp(right, targetright, 0.6f);
    
            if (Input.GetKeyDown(KeyCode.LeftShift)) {//用LeftShift切换奔跑
                run = !run;
            }
    
            jump = Input.GetKey(KeyCode.Space);//用Space来切换跳跃。
        }
    }
    

    4.控制端暂且如此,现在我们去初始化PlayerTestView,也就是视觉表现层的组件。

        struct PlayerAnimaId {
            public int baseAniam;//1D混合数的 ID号。
        };
    //将PlayerTestView需要用到的东西提前准备好
        [Header("===== 组件 ====")]
        Rigidbody rig;
        Animator animator;
        CapsuleCollider capsuleCollider;
        Transform player;
      [Header("===== 数据 ====")]
       float addSpeed = 1;//需要增加的速度,比如给人攻击推了一下
      float runSpeed = 3;//正常的跑步速度。
      float walkSpend = 1;//正常的走路速度。
      Vector3 moveDirection;//用于最终设置的参数,所有的移动变化都存储于此。
     public void init() {
        player = transform;
        rig = GetComponent<Rigidbody>();
        animator = GetComponent<Animator>();
        capsuleCollider = GetComponent<CapsuleCollider>();
        pad = new PlayerAnimaId();
        pad.baseAniam = Animator.StringToHash("walk");
    }
    
    

    现在我们把改准备的都准备,开始启动小姐姐移动的编写,我们这里设置为函数AnimaBlendAction

        void animaBlendAction(float right, float forward, bool run) {//设置转向以及速度
            Vector3 vec = (right * Vector3.right + forward * Vector3.forward);//设置方向
            float distance = vec.magnitude;
            if (distance < Vector3.kEpsilon) {//停下
                distance = 0;
                lerpSpeed = Mathf.Lerp(lerpSpeed, 0, 0.2f);//速度逐渐归零。
            } else {//开始行动
                player.forward = Vector3.Slerp(player.forward, vec, 0.2f);//设置转向
                float upperLimit = run ? runSpeed : walkSpend;
                lerpSpeed = Mathf.Lerp(lerpSpeed, upperLimit, 0.1f);//速度逐渐上升。
            }
            animator.SetFloat(pad.baseAniam, lerpSpeed);//控制人物动作
              moveDirection = Vector3.Project(moveDirection, Vector3.up);//每一次执行都要清理一边,但是需要保留起跳速度,我们这里先用 Vector3.up暂时用一下,代表角色每一次都是朝正上方起跳,如果后面需要斜面墙体什么的,到时候在将 Vector3.up替换掉。
            moveDirection += player.forward * lerpSpeed * addSpeed;
        }
    
        public void playerMove() {//这里是人物移动的最终执行,你们可以看到这里我写了两种方式,你们可以尝试一下。会有什么不同,
            //player.position += moveDirection ;//直接设置位置
            //rig.velocity = Vector3.zero//直接设置位置会和碰撞体产生不必要的加速度,我们不需要这个加速度。
             rig.velocity = moveDirection;//设置刚体速度
        }
    
    

    5.这里做好了然后,我们只需要去PlayerTestMediator调用即可。

        public override void OnRegister() {//绑定成功之后会调用这个API
            Debug.Log("OnRegister");
            playerView.init();
            UpdateManges.add_playerEventList_(keyController);
            UpdateManges.add_playerEventList_(playerAction);
        }
        public override void OnRemove() {//接触绑定之后调用这个API
            Debug.Log("OnRemove");
            UpdateManges.sub_playerEventList_(keyController);
            UpdateManges.sub_playerEventList_(playerAction);
        }
    
        void playerAction() {
            playerView.baseWalkRun(right, up, run);
            playerView.playerMove();
        }
    
    最终———— 参考

    上一节
    下一节

    相关文章

      网友评论

        本文标题:从零开始的RPG制作(2.1-人物控制)

        本文链接:https://www.haomeiwen.com/subject/fbtzgqtx.html