Skip to content

Instantly share code, notes, and snippets.

@verborghs
Last active October 4, 2019 10:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save verborghs/39a845c6b4772863f8478970ed8531ed to your computer and use it in GitHub Desktop.
Save verborghs/39a845c6b4772863f8478970ed8531ed to your computer and use it in GitHub Desktop.
using UnityEngine;
public class PlayerBehaviour : MonoBehaviour
{
public float Speed;
public float JumpHeight;
public float MaxSlope;
public float DynamicFriction;
private CharacterController _controller;
void Start()
{
_controller = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
var velocity = _controller.velocity;
var camera = Camera.main;
//Determine the player surface
var groundNormal = Vector3.up;
var groundPoint = Vector3.zero;
var characterCenter = transform.position + _controller.center;
var characterRayCastHeight = _controller.height / 2 + _controller.skinWidth * 2;
var groundLayer = LayerMask.GetMask("Walkable");
float radius = _controller.radius * 0.99f;
//determine point of floor contact
RaycastHit hitInfo;
var groundPointRay = new Ray(characterCenter, Vector3.down);
if (Physics.SphereCast(groundPointRay, radius, out hitInfo, characterRayCastHeight, groundLayer))
{
groundPoint = hitInfo.point;
}
//determine orientation of surface at floor contact
var groundNormalRay = new Ray(new Vector3(groundPoint.x, characterCenter.y, groundPoint.z), Vector3.down);
if (Physics.Raycast(groundNormalRay, out hitInfo, characterRayCastHeight))
{
groundNormal = hitInfo.normal;
}
//determine camera forward and right in xz-plane
Vector3 cameraForward = Vector3.Scale(camera.transform.forward, new Vector3(1, 0, 1)).normalized;
Vector3 cameraRight = Vector3.Scale(camera.transform.right, new Vector3(1, 0, 1)).normalized;
//get right stick input
float horizontalRight = UnityEngine.Input.GetAxis("RightStick_Horizontal");
float verticalRight = UnityEngine.Input.GetAxis("RightStick_Vertical");
//calculate the player orientation
Vector2 directionRight = new Vector2(horizontalRight, verticalRight);
directionRight = directionRight.sqrMagnitude > 2 ? directionRight.normalized : directionRight;
Vector3 worldDirectionRight = cameraRight * directionRight.x + cameraForward * directionRight.y;
if (!Mathf.Approximately(worldDirectionRight.sqrMagnitude, 0.0f))
{
Quaternion worldOrientation = Quaternion.LookRotation(worldDirectionRight, Vector3.up);
//rotate the player
transform.rotation = worldOrientation;
}
//gravity
velocity += Physics.gravity * Time.deltaTime;
//get left stick input
float horizontalLeft = UnityEngine.Input.GetAxis("LeftStick_Horizontal");
float verticalLeft = UnityEngine.Input.GetAxis("LeftStick_Vertical");
// calculate the player movement direction
Vector2 directionLeft = new Vector2(horizontalLeft, verticalLeft);
directionLeft = directionLeft.sqrMagnitude > 2 ? directionLeft.normalized : directionLeft;
Vector3 worldDirection = cameraRight * directionLeft.x + cameraForward * directionLeft.y;
if (_controller.isGrounded)
{
//only keep vertical velocity
velocity = Vector3.Scale(velocity, new Vector3(0, 1, 0));
//transform velocity into pure velocity along plane.
velocity = Vector3.ProjectOnPlane(velocity, groundNormal);
//calculate ground orientation
Vector3 groundTangent = worldDirection;
Vector3.OrthoNormalize(ref groundNormal, ref groundTangent);
Debug.Log(groundTangent);
Debug.Log(velocity.ToString("0.0000"));
//add movement to velocity
velocity += groundTangent * worldDirection.magnitude * Speed;
//jump
if (Input.GetButtonDown("A"))
{
//jump impulse
velocity = new Vector3(
velocity.x,
Mathf.Sqrt(2 * Physics.gravity.magnitude * JumpHeight),
velocity.z);
}
else
{
//interact
if (Input.GetButtonDown("B"))
{
var halfExtents = new Vector3(_controller.radius * 0.5f,
_controller.height / 2.0f, _controller.radius * 1.0f);
var forwardOffset = transform.forward * halfExtents.x;
var upOffset = transform.up * halfExtents.y;
var interactiveCenter = transform.position + forwardOffset + upOffset;
var interactiveLayer = LayerMask.GetMask("Interactive");
var interactives =
Physics.OverlapBox(interactiveCenter, halfExtents, transform.rotation, interactiveLayer);
if (interactives.Length > 0 )
{
var physics = interactives[0].GetComponentInParent<Rigidbody>();
Vector3 direction = interactives[0].transform.position - transform.position;
direction.y = 0;
physics.AddForce(direction * 8.0f, ForceMode.Impulse);
}
}
}
}
_controller.Move(velocity * Time.deltaTime);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment