//根据motorInput和steerInput为车轮碰撞器添加力矩 private void CalculateSingleWheelMotorTorque(float motorInput, float steerInput, BaseTrackData trackData, WheelCollider wheelCollider, float wheelSpeedKMPH) { AnimationCurve singleWheelMotorAnimationCurve = wheelFeaturesAnimationCurves.singleWheelMotorAnimationCurve; float direction = 0.0f; if (trackData is LeftTrackData) { direction = 1.0f; } else { direction = -1.0f; } if (motorInput == 0.0f && steerInput == 0.0f) { wheelCollider.motorTorque = 0.0f; } else if (motorInput == 0.0f && steerInput != 0.0f) { wheelCollider.motorTorque = steerInput * direction * singleWheelMotorAnimationCurve.Evaluate(wheelSpeedKMPH);; } else if (motorInput != 0.0f && steerInput == 0.0f) { wheelCollider.motorTorque = motorInput * singleWheelMotorAnimationCurve.Evaluate(wheelSpeedKMPH); } else //if (motorInput != 0.0f && steerInput != 0.0f) { wheelCollider.motorTorque = motorInput * singleWheelMotorAnimationCurve.Evaluate(wheelSpeedKMPH); } }
//更新履带控制, private float UpdateTrackController(float motorInput, float steerInput, BaseTrackData trackData) { //总转向扭矩在Y轴上的值 float totalWheelSteerTorqueYValue = 0.0f; //准备工作,用于定义各种实例 #region Prepare UpperWheelData[] upperWheelArray = trackData.upperWheelDataArray; SuspendedWheelData[] suspendedWheelDataArray = trackData.suspendedWheelDataArray; SkinnedMeshRenderer trackRender = trackData.trackSkinnedMeshRenderer; WheelAndBoneTransformOffsetDirection wheelAndBoneTransformOffsetDirection = adjustParameters.wheelAndBoneTransformOffsetDirection; bool inverseWheelAndBoneTransformOffsetDirection = adjustParameters.inverseWheelAndBoneTransformOffsetDirection; float singleWheelAndBoneTransfromVerticalOffset = adjustParameters.singleWheelAndBoneTransfromVerticalOffset; WheelRotateAxis wheelRotateAxis = adjustParameters.wheelRotateAxis; bool inverseWheelRotateDirection = adjustParameters.inverseWheelRotateDirection; TrackTextureOffsetType trackTextureOffsetType = adjustParameters.trackTextureOffsetType; bool inverseTrackTextureOffsetDirection = adjustParameters.inverseTrackTextureOffsetDirection; float singleTrackTextureOffsetSpeedMultiplier = adjustParameters.singleTrackTextureOffsetSpeedMultiplier; float inverseWheelAndBoneTransformOffsetDirectionFlag = 0.0f; //根据inverseWheelAndBoneTransformOffsetDirection,指定inverseWheelAndBoneTransformOffsetDirectionFlag的值(作为车轮模型和bone位移的乘数) if (inverseWheelAndBoneTransformOffsetDirection == true) { inverseWheelAndBoneTransformOffsetDirectionFlag = -1.0f; } else { inverseWheelAndBoneTransformOffsetDirectionFlag = 1.0f; } //车轮模型旋转方向乘数 float inverseWheelRotateDirectionFlag = 0.0f; if (inverseWheelRotateDirection == true) { inverseWheelRotateDirectionFlag = -1.0f; } else { inverseWheelRotateDirectionFlag = 1.0f; } //履带贴图偏移方向乘数 float inverseTrackTextureOffsetDirectionFlag = 0.0f; if (inverseTrackTextureOffsetDirection == true) { inverseTrackTextureOffsetDirectionFlag = -1.0f; } else { inverseTrackTextureOffsetDirectionFlag = 1.0f; } //车轮平均每分钟旋转次数 float wheelAverageSpeedRpm = CalculateWheelsAverageRPM(suspendedWheelDataArray); //车轮平均每分钟旋转度数(Time.fixedDeltaTime作为乘数) float wheelAverageSpeedDegreePerSecond = Time.fixedDeltaTime * wheelAverageSpeedRpm * 360.0f / 60.0f; #endregion //上车轮模型数组处理 #region Handle UpperWheelArray for (int i = 0; i < upperWheelArray.Length; i++) { UpperWheelData upperWheelData = upperWheelArray[i]; Transform wheelTransform = upperWheelData.wheelTransform; if (wheelRotateAxis == WheelRotateAxis.X) { wheelTransform.rotation = wheelTransform.rotation * Quaternion.Euler(inverseWheelRotateDirectionFlag * wheelAverageSpeedDegreePerSecond, 0.0f, 0.0f); } else if (wheelRotateAxis == WheelRotateAxis.Y) { wheelTransform.rotation = wheelTransform.rotation * Quaternion.Euler(0.0f, inverseWheelRotateDirectionFlag * wheelAverageSpeedDegreePerSecond, 0.0f); } else //(wheelRotateAxis == WheelRotateAxis.Z) { wheelTransform.rotation = wheelTransform.rotation * Quaternion.Euler(0.0f, 0.0f, inverseWheelRotateDirectionFlag * wheelAverageSpeedDegreePerSecond); } } #endregion //下车轮数据数组处理 #region Handle SuspendedWheelDataArray for (int i = 0; i < suspendedWheelDataArray.Length; i++) { SuspendedWheelData suspendedWheelData = suspendedWheelDataArray[i]; WheelCollider wheelCollider = suspendedWheelData.wheelCollider; wheelCollider.wheelDampingRate = Mathf.Lerp(100.0f, 0.0f, Mathf.Abs(motorInput)); //移动目标位置 Vector3 wheelTranformTargetPosition = Vector3.zero; Quaternion wheelTransfromTargetRotation = Quaternion.identity; //获取车轮碰撞器的世界坐标位置与旋转 wheelCollider.GetWorldPose(out wheelTranformTargetPosition, out wheelTransfromTargetRotation); //车轮碰撞器竖值方向 Vector3 wheelColliderVerticalDirection = Vector3.zero; if (wheelAndBoneTransformOffsetDirection == WheelAndBoneTransformOffsetDirection.X) { wheelColliderVerticalDirection = wheelCollider.transform.right * inverseWheelAndBoneTransformOffsetDirectionFlag; } else if (wheelAndBoneTransformOffsetDirection == WheelAndBoneTransformOffsetDirection.Y) { wheelColliderVerticalDirection = wheelCollider.transform.up * inverseWheelAndBoneTransformOffsetDirectionFlag; } else //wheelAndBoneTransformOffsetDirection == WheelAndBoneTransformOffsetDirection.Z { wheelColliderVerticalDirection = wheelCollider.transform.forward * inverseWheelAndBoneTransformOffsetDirectionFlag; } //由于履带存在厚度,骨架与车轮模型需在竖直方向上偏移 Transform wheelBoneTransform = suspendedWheelData.wheelBoneTransform; Vector3 wheelBoneTransformVerticalOffset = wheelColliderVerticalDirection * singleWheelAndBoneTransfromVerticalOffset; wheelBoneTransform.position = wheelTranformTargetPosition + wheelBoneTransformVerticalOffset; Transform wheelTransform = suspendedWheelData.wheelTransform; Vector3 wheelTranformVerticalOffset = wheelColliderVerticalDirection * singleWheelAndBoneTransfromVerticalOffset; wheelTransform.position = wheelTranformTargetPosition + wheelTranformVerticalOffset; //根据旋转轴和每分钟旋转度数控制车轮模型旋转 if (wheelRotateAxis == WheelRotateAxis.X) { wheelTransform.rotation = wheelTransform.rotation * Quaternion.Euler(inverseWheelRotateDirectionFlag * wheelAverageSpeedDegreePerSecond, 0.0f, 0.0f); } else if (wheelRotateAxis == WheelRotateAxis.Y) { wheelTransform.rotation = wheelTransform.rotation * Quaternion.Euler(0.0f, inverseWheelRotateDirectionFlag * wheelAverageSpeedDegreePerSecond, 0.0f); } else //wheelRotateAxis == WheelRotateAxis.Z { wheelTransform.rotation = wheelTransform.rotation * Quaternion.Euler(0.0f, 0.0f, inverseWheelRotateDirectionFlag * wheelAverageSpeedDegreePerSecond); } //根据车轮碰撞器的半径和转速计算出车轮的速度 float wheelSpeedKMPH = Mathf.Abs(ConvertSingleWheelRPMToKMPH(wheelCollider.radius, wheelCollider.rpm)); CalculateSingleWheelMotorTorque(motorInput, steerInput, trackData, wheelCollider, wheelSpeedKMPH); CalculateSingleWheelBrakeTorque(motorInput, steerInput, wheelCollider, wheelSpeedKMPH); float singleWheelSteerTorqueYValue = CalculateSingleWheelSteerTorqueYValue(motorInput, steerInput, wheelCollider, wheelSpeedKMPH); totalWheelSteerTorqueYValue = totalWheelSteerTorqueYValue + singleWheelSteerTorqueYValue; } #endregion //履带贴图偏移处理 #region Handle TrackSkinnedMeshRenderer Vector2 trackMainTextureOffset = trackRender.material.GetTextureOffset("_MainTex"); Vector2 trackBumpMapOffset = trackRender.material.GetTextureOffset("_BumpMap"); if (trackTextureOffsetType == TrackTextureOffsetType.X) { trackMainTextureOffset.x = Mathf.Repeat(trackMainTextureOffset.x + (inverseTrackTextureOffsetDirectionFlag * wheelAverageSpeedDegreePerSecond * singleTrackTextureOffsetSpeedMultiplier) / 360.0f, 1.0f); trackBumpMapOffset.x = Mathf.Repeat(trackBumpMapOffset.x + (inverseTrackTextureOffsetDirectionFlag * wheelAverageSpeedDegreePerSecond * singleTrackTextureOffsetSpeedMultiplier) / 360.0f, 1.0f); } else { trackMainTextureOffset.y = Mathf.Repeat(trackMainTextureOffset.y + (inverseTrackTextureOffsetDirectionFlag * wheelAverageSpeedDegreePerSecond * singleTrackTextureOffsetSpeedMultiplier) / 360.0f, 1.0f); trackBumpMapOffset.y = Mathf.Repeat(trackBumpMapOffset.y + (inverseTrackTextureOffsetDirectionFlag * wheelAverageSpeedDegreePerSecond * singleTrackTextureOffsetSpeedMultiplier) / 360.0f, 1.0f); } trackRender.material.SetTextureOffset("_MainTex", trackMainTextureOffset); trackRender.material.SetTextureOffset("_BumpMap", trackBumpMapOffset); #endregion return(totalWheelSteerTorqueYValue); }
//判断坦克履带数据是否设置正确 public bool CheckIfTrackDataSettingIsCorrect(BaseTrackData trackData) { string trackDataName = string.Empty; //判断trackData是LeftTrackData还是RightTrackData if (trackData is LeftTrackData) { trackDataName = "LeftTrackData"; } else { trackDataName = "RightTrackData"; } //创建用于存储内部数据的对象 UpperWheelData[] upperWheelArray = trackData.upperWheelDataArray; SuspendedWheelData[] suspendedWheelDataArray = trackData.suspendedWheelDataArray; SkinnedMeshRenderer trackRender = trackData.trackSkinnedMeshRenderer; //遍历数组,如果为完全设置正确,返回false for (int i = 0; i < upperWheelArray.Length; i++) { UpperWheelData upperWheelData = upperWheelArray[i]; Transform wheelTransform = upperWheelData.wheelTransform; if (wheelTransform == null) { string message = string.Format("You are not set {0}-> UpperWheelData0{1} -> Wheel Model !", trackDataName, i); EditorUtility.DisplayDialog("Track Simulator", message, "OK"); return(false); } } for (int i = 0; i < suspendedWheelDataArray.Length; i++) { SuspendedWheelData suspendedWheelData = suspendedWheelDataArray[i]; Transform wheelTransform = suspendedWheelData.wheelTransform; Transform wheelBoneTransform = suspendedWheelData.wheelBoneTransform; WheelCollider wheelCollider = suspendedWheelData.wheelCollider; if (wheelTransform == null) { string message = string.Format("You are not set {0} -> SuspendedWheelData0{1} -> Wheel Model !", trackDataName, i); EditorUtility.DisplayDialog("Track Simulator", message, "OK"); return(false); } if (wheelBoneTransform == null) { string message = string.Format("You are not set {0} -> SuspendedWheelData0{1} -> Wheel Bone !", trackDataName, i); EditorUtility.DisplayDialog("Track Simulator", message, "OK"); return(false); } if (wheelCollider == null) { string message = string.Format("You are not set {0} -> suspendedWheelData0{1} -> Wheel Collider !", trackDataName, i); EditorUtility.DisplayDialog("Track Simulator", message, "OK"); return(false); } } if (trackRender == null) { string message = string.Format("You are not set {0} -> Track SkinnedMeshRenderer !", trackDataName); EditorUtility.DisplayDialog("Track Simulator", message, "OK"); return(false); } return(true); }