Android游戏

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

2019-04-25  本文已影响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();
    }
最终———— 参考

上一节
下一节

上一篇下一篇

猜你喜欢

热点阅读