csharp 用于移动,跳跃和重力的Unity字符驱动程序/控制器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 用于移动,跳跃和重力的Unity字符驱动程序/控制器相关的知识,希望对你有一定的参考价值。

using UnityEngine;
using System.Collections;

[RequireComponent (typeof(CharacterController))]
public class CharacterDriver : MonoBehaviour {

	public class CharacterState
	{
		public Vector3 position = new Vector3();
		
		public Vector3 velocity = new Vector3();
		
		public CharacterState()
		{
			
		}
		
		public CharacterState(CharacterState s)
		{
			this.position = s.position;
			this.velocity = s.velocity;
		}
		
		public CharacterState(Vector3 position,Vector3 velocity)
		{
			this.position = position;
			
			this.velocity = velocity;
		}
		
		public static CharacterState Lerp(CharacterState from, CharacterState to, float t)
		{
			return new CharacterState(Vector3.Lerp(from.position, to.position, t), Vector3.Lerp(from.velocity, to.velocity, t));
		}

		public static implicit operator string(CharacterState s)
		{
			return s.ToString();
		}


		public string ToString()
		{
			return "p: " + this.position + " v: " + this.velocity;
		}
	}

	public float maxSurgeSpeed = 5f; // Forward, backward
	public float maxSwaySpeed = 5f; // Side to side
	public float jumpHeight = 4f;

	CharacterController characterController;


	// We use these to smooth between values in certain framerate situations in the `Update()` loop
	CharacterState currentState = new CharacterState();
	CharacterState previousState = new CharacterState();

	// Use this for initialization
	void Start () {
		this.characterController = GetComponent<CharacterController>();

		this.ResetCharacterDriver();
	}

	// Use this to reset any built up forces
	[ContextMenu("Reset Character State")]
	void ResetCharacterDriver()
	{
		// Set the transition state
		this.currentState = new CharacterState(transform.position, Vector3.zero);
		this.previousState = this.currentState;
	}

	float t = 0f;
	float dt = 0.01f;
	float currentTime = 0f;
	float accumulator = 0f;

	bool isFirstPhysicsFrame = true;

	// Update is called once per frame
	void Update () 
	{
		// Fixed deltaTime rendering at any speed with smoothing
		// Technique: http://gafferongames.com/game-physics/fix-your-timestep/
		float frameTime = Time.time - currentTime;
		this.currentTime = Time.time;
		
		this.accumulator += frameTime;
		
		while (this.accumulator >= this.dt)
		{
			this.previousState = this.currentState;
			this.currentState = this.MoveUpdate(this.currentState, this.dt);

			//integrate(state, this.t, this.dt);
			Vector3 movementDelta = currentState.position - transform.position;
			this.characterController.Move(movementDelta);
			this.currentState = new CharacterState(transform.position, this.currentState.velocity);

			accumulator -= this.dt;
			this.t += this.dt;
		}

		// Reset it
		this.isFirstPhysicsFrame = true;
	}

	CharacterState MoveUpdate(CharacterState state, float deltaTime)
	{
		CharacterState currentState = new CharacterState(state);

		// Add the gravity
		if(this.characterController.isGrounded)
		{
			// Remove the gravity in the direction we hit (ground)
			currentState.velocity -= Vector3.Project(currentState.velocity, Physics.gravity.normalized);
		}

		currentState.velocity += Physics.gravity * deltaTime;

		
		// Jumping
		if(this.characterController.isGrounded && Input.GetButtonDown("Jump") && this.isFirstPhysicsFrame) 
		{
			// Play jump sound effect here

			// Jump the player
			currentState.velocity += -1f * Physics.gravity.normalized * this.CalculateJumpVerticalSpeed(this.jumpHeight);
		}
		


		// Movement Surge and Sway
		// Elliptical player/character movement. See diagram for more info:
		// 		http://i.imgur.com/am2OYj1.png
		float angle =  Mathf.Atan2(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
		float surgeSpeed = Mathf.Abs(Input.GetAxis("Vertical")) * this.maxSurgeSpeed * Mathf.Sin(angle); // Forward and Backward
		float swaySpeed = Mathf.Abs(Input.GetAxis("Horizontal")) * this.maxSwaySpeed * Mathf.Cos(angle); // Left and Right



		// Get the camera directions without the Y component
		Vector3 cameraForwardNoY = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
		Vector3 cameraRightNoY = Vector3.Scale(Camera.main.transform.right, new Vector3(1, 0, 1)).normalized;

		Vector3 movementDelta = (cameraForwardNoY*surgeSpeed + cameraRightNoY*swaySpeed) * deltaTime;
		movementDelta += currentState.velocity * deltaTime;

		currentState.position += movementDelta;

		// Set this so we don't get confused later on
		this.isFirstPhysicsFrame = false;

		return currentState;
	}


	float CalculateJumpVerticalSpeed(float targetJumpHeight)
	{
		// From the jump height and gravity we deduce the upwards speed 
		// for the character to reach at the apex.
		// See for formula: http://math.stackexchange.com/a/222585/60008
		return Mathf.Sqrt(2f * targetJumpHeight * Physics.gravity.magnitude);
	}
}

以上是关于csharp 用于移动,跳跃和重力的Unity字符驱动程序/控制器的主要内容,如果未能解决你的问题,请参考以下文章

Unity中角色跳跃时如何禁用重力?

我如何在 Unity 中制作随着速度跳跃而移动的东西?

unity第一人称控制器怎么使用鼠标点击

unity第一人称如何设置

玩家跳跃高度不一致 - Unity

Unity 实现角色移动视角旋转以及跳跃