Да.
Вот код мотоцикла:
using UnityEngine;
using System.Collections;
public class MotorbikeController : MonoBehaviour
{
public enum State {Idle, Braking, Accelerating};
public State state = State.Idle;
public Transform steeringWheel;
public Transform frontWheelTransformer;
public Transform rearWheelTransformer;
public WheelCollider rearWheelCollider;
public WheelCollider frontWheelCollider;
public float maxSteerAngle = 30f;
public float power = 50f;
public float maxRpm = 40000;
public float breakingCof = 2f;
public float Speed {get; private set;}
public float Steer {get; set;}
private Vector3 prevPos;
public void Accelerate(float effort)
{
state = State.Accelerating;
rearWheelCollider.brakeTorque = 0;
frontWheelCollider.brakeTorque = 0;
if (rearWheelCollider.rpm < maxRpm) {
rearWheelCollider.motorTorque += effort * power;
}
}
public void Brake(float frontEffort, float rearEffort)
{
state = State.Braking;
rearWheelCollider.motorTorque = 0;
rearWheelCollider.brakeTorque = breakingCof * rearEffort;
frontWheelCollider.brakeTorque = breakingCof * frontEffort;
}
public void Turn(float balance = 0f)
{
//steeringWheel.localRotation = Quaternion.Euler(balance,0,0);
frontWheelCollider.steerAngle = balance*maxSteerAngle;
}
void AcceleratorCullDown ()
{
if (rearWheelCollider.motorTorque < 0.001f) {
rearWheelCollider.motorTorque = 0;
return;
}
rearWheelCollider.motorTorque *= 0.99f;
}
void BrakesCullDown ()
{
if (rearWheelCollider.brakeTorque < 0.001f) {
rearWheelCollider.brakeTorque = 0;
return;
}
rearWheelCollider.brakeTorque *= 0.5f;
}
void FixedUpdate()
{
if (state == State.Idle) {
AcceleratorCullDown();
BrakesCullDown();
}
state = State.Idle;
Speed = (transform.position - prevPos).magnitude/Time.fixedDeltaTime;
prevPos = transform.position;
}
void Update()
{
Quaternion rotQuat;
Vector3 pos;
rearWheelCollider.GetWorldPose(out pos, out rotQuat);
rearWheelTransformer.position = pos;
rearWheelTransformer.rotation = rotQuat;
frontWheelCollider.GetWorldPose(out pos, out rotQuat);
frontWheelTransformer.position = pos;
frontWheelTransformer.rotation = rotQuat;
}
}
А это код персонажа:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public enum State {Stop,Riding,Crawling};
public MotorbikeController motorbike;
public PlayerInput input;
public float brakesBalance = 0.6f;
private bool ragDollMode = true;
private Animator animator;
public State state = State.Stop;
private Rigidbody motorbikeBody;
private float tiltAngle;
Ray ray;
float turn;
void SetRagDollMode (bool enable)
{
if (ragDollMode == enable) {
return;
}
Physics.IgnoreLayerCollision(8,9,!enable);
animator.enabled = !enable;
var i = 0;
foreach (var rBody in GetComponentsInChildren<Rigidbody> ())
{
i++;
if (i == 1)
{
rBody.isKinematic = enable;
continue;
}
rBody.isKinematic = !enable;
rBody.detectCollisions = enable;
}
ragDollMode = enable;
}
// Use this for initialization
void Start ()
{
animator = GetComponentInChildren<Animator>();
motorbikeBody = motorbike.GetComponent<Rigidbody>();
SetRagDollMode (false);
ray = new Ray (transform.position, Vector3.down);
motorbikeBody.centerOfMass = Vector3.up;
}
void Update()
{
ProcessInput();
}
void FixedUpdate()
{
var rotation = HelperFunctions.GetNonABSeulerValue(motorbikeBody.rotation.eulerAngles);
RaycastHit hitInfo;
Physics.Raycast(ray, out hitInfo, 3f);
Debug.DrawRay(motorbike.transform.position, motorbike.transform.up);
Debug.DrawRay(motorbike.transform.position, hitInfo.normal, Color.blue);
var preTiltAngel = Vector3.Angle(motorbike.transform.up, hitInfo.normal);
if (preTiltAngel != 90) {
tiltAngle = preTiltAngel;
}
if (state != State.Crawling)
{
if (motorbike.Speed < 1.1f)
{
state = State.Stop;
}
else
{
state = State.Riding;
}
}
if (tiltAngle < ((int)motorbike.Speed | 10)) {
motorbikeBody.transform.Rotate(0,0,-input.Tilt);
}
if (state == State.Stop)
{
if (tiltAngle > 5)
{
motorbikeBody.constraints = RigidbodyConstraints.FreezeRotationZ;
if (tiltAngle > 10) {
var ideal = rotation;
ideal.z = 0;
motorbikeBody.rotation = Quaternion.Euler(Vector3.Lerp(rotation, ideal, 0.1f));
}
}
else
{
motorbikeBody.constraints = RigidbodyConstraints.None;
}
}
else if (state == State.Riding)
{
motorbikeBody.constraints = RigidbodyConstraints.FreezeRotationZ;
if (input.Tilt == 0 || tiltAngle > ((int)motorbike.Speed | 10)) {
var ideal = rotation;
ideal.z = 0;
motorbikeBody.rotation = Quaternion.Euler(Vector3.Lerp(rotation, ideal, 0.1f));
}
}
else
{
motorbikeBody.constraints = RigidbodyConstraints.None;
}
animator.SetFloat("speed", motorbike.Speed);
animator.SetFloat("direction", rotation.z);
}
void OnTriggerEnter(Collider other) {
if (other.gameObject.layer == LayerMask.NameToLayer("Default"))
{
var holder = GetComponent<FixedJoint>();
Destroy(holder);
state = State.Crawling;
SetRagDollMode(true);
}
}
void ProcessInput ()
{
turn = Mathf.Lerp(turn,input.Tilt,0.1f);
motorbike.Turn(turn);
if (input.Accelerating > 0) {
motorbike.Accelerate(input.Accelerating);
}
if (input.Braking > 0) {
motorbike.Brake(input.Braking * brakesBalance, input.Braking * (1f-brakesBalance));
}
}
}