unity3d boxcollider的wheelcollider轮胎锁死问题

WheelCollider相关问题【unity3d吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:74,250贴子:
WheelCollider相关问题收藏
我在制作一个坦克模型,给坦克轮子加上WheelCollider之后,在运行中发现,当车辆并非完全静止的时候(即震动、轻微位移(旋转不算)),给车辆施加向前推力或向后拉力车辆均可移动,但是如果车辆完全静止(即不震动、不位移),这时候给车辆添加力虽然坐标显示的数字会有变化但是在实际场景中坦克将无法起步,如果加大推力,坦克会被推得几乎竖起来,然后才会正常运动,有没有吧友遇到过类似的情况呢?是如何解决的呢?求解答
自己顶一下
怕不是刚体质量太小
不知道你为什么非要轮子转动。把坦克的轮子做成动画,再移动不就可以了
登录百度帐号推荐应用Unity3d 官方资源Car的主控脚本CarController翻译与详解 - 博客频道 - CSDN.NET
narutojzm1的博客
分类:游戏编程
在Unity3D官方资源中Standard Assets –&Vehicles–&Car是赛车的相关资源,包括赛车模型、赛车控制脚本等。虽然用起来很方便,但是由于对有些脚本理解不彻底,就用不好。尤其是主要控制脚本CarController,我此次就对这个脚本进行了全面解析
二.CarController
1.主要函数流程图
整个CarController脚本主要是通过共有函数Move对赛车进行控制
2.代码类型定义部分
internal enum CarDriveType
FrontWheelDrive,
RearWheelDrive,
FourWheelDrive
internal enum SpeedType
3.代码定义部分
[SerializeField] private CarDriveType m_CarDriveType = CarDriveType.FourWheelD
[SerializeField] private WheelCollider[] m_WheelColliders = new WheelCollider[4];
[SerializeField] private GameObject[] m_WheelMeshes = new GameObject[4];
[SerializeField] private WheelEffects[] m_WheelEffects = new WheelEffects[4];
[SerializeField] private Vector3 m_CentreOfMassO
[SerializeField] private float m_MaximumSteerA
[Range(0, 1)] [SerializeField] private float m_SteerH
[Range(0, 1)] [SerializeField] private float m_TractionC
[SerializeField] private float m_FullTorqueOverAllW
[SerializeField] private float m_ReverseT
[SerializeField] private float m_MaxHandbrakeT
[SerializeField] private float m_Downforce = 100f;
[SerializeField] private SpeedType m_SpeedT
[SerializeField] private float m_Topspeed = 200;
[SerializeField] private static int NoOfGears = 5;
[SerializeField] private float m_RevRangeBoundary = 1f;
[SerializeField] private float m_SlipL
[SerializeField] private float m_BrakeT
4.函数Move
public void Move(float steering, float accel, float footbrake, float handbrake)
Debug.Log ("***************************: " + footbrake + " " + handbrake);
for (int i = 0; i & 4; i++)
m_WheelColliders[i].GetWorldPose(out position, out quat);
m_WheelMeshes[i].transform.position =
m_WheelMeshes[i].transform.rotation =
steering = Mathf.Clamp(steering, -1, 1);
AccelInput = accel = Mathf.Clamp(accel, 0, 1);
BrakeInput = footbrake = -1*Mathf.Clamp(footbrake, -1, 0);
handbrake = Mathf.Clamp(handbrake, 0, 1);
m_SteerAngle = steering*m_MaximumSteerA
m_WheelColliders[0].steerAngle = m_SteerA
m_WheelColliders[1].steerAngle = m_SteerA
SteerHelper();
ApplyDrive(accel, footbrake);
CapSpeed();
if (handbrake & 0f)
var hbTorque = handbrake*m_MaxHandbrakeT
m_WheelColliders[2].brakeTorque = hbT
m_WheelColliders[3].brakeTorque = hbT
CalculateRevs();
GearChanging();
AddDownForce();
CheckForWheelSpin();
TractionControl();
5.函数SteerHelper,重点属性:m_SteerHelper
private void SteerHelper()
for (int i = 0; i & 4; i++)
m_WheelColliders[i].GetGroundHit(out wheelhit);
if (wheelhit.normal == Vector3.zero)
if (Mathf.Abs(m_OldRotation - transform.eulerAngles.y) & 10f)
var turnadjust = (transform.eulerAngles.y - m_OldRotation) * m_SteerH
Quaternion velRotation = Quaternion.AngleAxis(turnadjust, Vector3.up);
m_Rigidbody.velocity = velRotation * m_Rigidbody.
m_OldRotation = transform.eulerAngles.y;
我通过实践,发现的效果就是如果m_SteerHelper为0,车转角度时就很死,如果为1,车转角度就特别灵活。所以这个属性得看个人的情况进行调整
6.函数TranctionControl,重点属性m_TractionControl
private void TractionControl()
WheelHit wheelH
switch (m_CarDriveType)
case CarDriveType.FourWheelDrive:
for (int i = 0; i & 4; i++)
m_WheelColliders[i].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
case CarDriveType.RearWheelDrive:
m_WheelColliders[2].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
m_WheelColliders[3].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
case CarDriveType.FrontWheelDrive:
m_WheelColliders[0].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
m_WheelColliders[1].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
private void AdjustTorque(float forwardSlip)
if (forwardSlip &= m_SlipLimit && m_CurrentTorque &= 0)
m_CurrentTorque -= 10 * m_TractionC
m_CurrentTorque += 10 * m_TractionC
if (m_CurrentTorque & m_FullTorqueOverAllWheels)
m_CurrentTorque = m_FullTorqueOverAllW
从上面的函数可以看出来,属性m_TractionControl控制着牵引力每次增加或者减少的增量大小。
我们再来看另外一段Start中的代码
m_CurrentTorque = m_FullTorqueOverAllWheels - (m_TractionControl*m_FullTorqueOverAllWheels);
也就是说,如果m_TractionControl为1,那么一开始的汽车扭矩力就是0了,然后通过上面函数TranctionControl中的代码,每次10个力地增加。
我们会发现,每次启动汽车都会非常缓慢,而且如果爬坡时一次没冲上去,停在了半坡,再想冲上去,非常困难,因为这个时候扭矩力很小,动力不足;
如果我们把m_TractionControl设置为0,那么汽车一开始的动力就是满的,也不会再增加减少,但是汽车启动可能会特别快。
如果我们把m_TractionControl设置为0.5,那么汽车一开始就拥有满动力一半的动力,然后另外一半动力会动态地变化。
所以只要把握住了上面几点,就根据自己需要设置该属性就好了
7.函数CalculateRevs(),重点属性Revs
private void CalculateRevs()
CalculateGearFactor();
var gearNumFactor = m_GearNum/(float) NoOfG
var revsRangeMin = ULerp(0f, m_RevRangeBoundary, CurveFactor(gearNumFactor));
var revsRangeMax = ULerp(m_RevRangeBoundary, 1f, gearNumFactor);
Revs = ULerp(revsRangeMin, revsRangeMax, m_GearFactor);
其中有个比较奇怪的地方是计算RevsRangeMin,对档位因子使用了CurveFactor曲线函数,我的理解是,由于档位与转速的对应关系不是y = x这种简单的关系,所以不能直接使用gearNumFactor当做转速的比例系数,所以需要做一次转换,也就是说,档位或者速度与转速之间的对应关系是转速 = 1- (1-X)(1-X)。请看我根据这个函数做出来的曲线
至于为什么计算最大转速时,又没有使用这个函数,我就还没有搞清楚呢
8.函数CalculateGearFactor
private void CalculateGearFactor()
float f = (1/(float) NoOfGears);
var targetGearFactor = Mathf.InverseLerp(f*m_GearNum, f*(m_GearNum + 1), Mathf.Abs(CurrentSpeed/MaxSpeed));
m_GearFactor = Mathf.Lerp(m_GearFactor, targetGearFactor, Time.deltaTime*5f);
从上面我们可以看出,至少档位速度之间的对应关系,大致是直线性,不是曲线的。不然上面的那种反插值函数,可能就得使用曲线变换函数了。
其他的函数也有些有意思的函数,我就不在这里列举了。我上传了我注释版的CarController,希望能给有用的朋友一些启发。我的好多理解也可能不对,只是自圆其说,我日后再研究有结果会再更新的
我的上传注释版链接:
narutojzm1
排名:千里之外
(3)(6)(4)(7)(49)(14)(4)(1)鏌ョ湅: 11610|鍥炲?: 5
UID锛

我要回帖

更多关于 unity3d collider 的文章

 

随机推荐