Показать сообщение отдельно
Старый 03.09.2015, 11:02   #3
ІГРОГРАЙКО
ПроЭктировщик
 
Аватар для ІГРОГРАЙКО
 
Регистрация: 20.06.2009
Адрес: Україна
Сообщений: 152
Написано 10 полезных сообщений
(для 24 пользователей)
Ответ: Проблема физики двуколесного транспорта

Да.

Вот код мотоцикла:
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));
		}
	}
}
__________________
Blitz3D, XNA, WebGL, OpenGL, Unity3D
PC: ASUS A55VM Core i3 (2.4Ghz), 6 Gb RAM, Nvidia GF 630M GT 2Gb
(Offline)
 
Ответить с цитированием