山寨Besiege(五)车轮

自从有了电,生活真方便。

自从有了引擎,做游戏真方便。

再度感慨下社会分工合作的神奇,假如自己做一个WheelCollider,不知道复杂到哪里去了。


Unity的WheelCollider是个很高端的玩意,不光会滚,还自带悬挂弹力模拟,所以做出像越野摩托那种弹力十足的东西也应该不难。

轮子就没什么好贴图的了,直接选讲参数:

1.Wheel Damping Rate

        这个阻尼的单位是什么官方文档没怎么讲清楚,反正肯定不是百分比。后面可以看到我用调节它的方式来实现自动刹车。

2.Suspension

        由于Besiege中的轮子没怎么见弹性,可能中世纪那会欧洲木有橡胶吧,我也直接把悬挂参数都关了。

3.摩擦力曲线

        注意这个值设的过大轮子可是会朝相反方向跑的哦。


官方的车轮教程也讲了,WheelCollider只管实现物理特性,但是它本身是不会转动的,要表现外观的滚动,就要在下面绑个轮子模型,用代码作同步控制。

同时千万注意,不要让WheelCollider转动,一不小心就会掉到地面以下去,查了下资料,结合个人思考,推测是悬挂系统需要轮子往下射射线计算离地面高度,要是这个射线歪了,高度就出错,位置也就相应出错。


所以MotorWheel的Prefab最终这样设计:

MotorWheel(加刚体并锁住XZ角度,绑MotorWheelCtrl脚本)

        Wheel(WheelCollider)

                GameObject(空物体)

                        Cylinder(圆柱体轮子外观)

因为直接拷了官方示例代码,轮子外观也沿用了官方的结构,可能实际上去除GameObject,只需要三层结构足矣。


下面是控制脚本:

using UnityEngine;
using System.Collections;

public class MotorWheelCtrl : MonoBehaviour {

    public WheelCollider wheel;
    public float maxMotorTorque = 50;

    public KeyCode forwardKey = KeyCode.UpArrow;
    public KeyCode backKey = KeyCode.DownArrow;

	void Start () 
    {
	    wheel = GetComponentInChildren();
	}

	void Update () 
    {
        if (Input.GetKey(forwardKey))
        {
            OnWheelForwardBtn(); 
        }

        if (Input.GetKey(backKey))
        {
            OnWheelBackBtn();
        }

        if (Input.GetKeyUp(forwardKey) || Input.GetKeyUp(backKey))
        {
            OnWheelCtrlBtnUp();
        }

        ApplyLocalPositionToVisuals(wheel);
	}

    public void OnWheelForwardBtn()
    {
        wheel.motorTorque = maxMotorTorque;
        wheel.wheelDampingRate = 0.5f;
    }

    public void OnWheelBackBtn()
    {
        wheel.motorTorque = -maxMotorTorque;
        wheel.wheelDampingRate = 0.5f;
    }

    public void OnWheelCtrlBtnUp()
    {
        wheel.motorTorque = 0;
        wheel.wheelDampingRate = 20.0f;
    }

    //让轮子外观一起滚动
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0)
        {
            return;
        }

        Transform visualWheel = collider.transform.GetChild(0);

        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);

        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }
}


很简单,没什么好说的。



自此关键部件的技术验证都通过了,然后我试着把木块、转向轴、轮子三者用FixedJoint像这样钉在一起:

山寨Besiege(五)车轮_第1张图片

测试也是能顺利运作的。


需要注意的是物体一旦使用FixedJoint组件,则不再受重力影响,所以具体的动态连结实现方式肯定要作一番考量。各零件的封装肯定也都要作合适的修改。

接下来做这些改动工作,最后再整合游戏。

你可能感兴趣的:(游戏编程)