charactercontroller2k

This commit is contained in:
mischa 2023-12-13 16:24:37 +01:00
parent 0c98a51012
commit 1c46530f68
13 changed files with 2282 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2427a0fd987cc4d239b45820402d37f1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29d02e23dd78c434baee064aae1caed9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,56 @@
using UnityEngine;
namespace Controller2k
{
// Collision info used by the OpenCharacterController and sent to the OnOpenCharacterControllerHit message.
public struct CollisionInfo
{
// The collider that was hit by the controller.
public readonly Collider collider;
// The controller that hit the collider.
public readonly CharacterController2k controller;
// The game object that was hit by the controller.
public readonly GameObject gameObject;
// The direction the character Controller was moving in when the collision occured.
public readonly Vector3 moveDirection;
// How far the character has travelled until it hit the collider.
public readonly float moveLength;
// The normal of the surface we collided with in world space.
public readonly Vector3 normal;
// The impact point in world space.
public readonly Vector3 point;
// The rigidbody that was hit by the controller.
public readonly Rigidbody rigidbody;
// The transform that was hit by the controller.
public readonly Transform transform;
// Constructor
// openCharacterController: The character controller that hit.
// hitInfo: The hit info.
// directionMoved: Direction moved when collision occured.
// distanceMoved: How far the character has travelled until it hit the collider.
public CollisionInfo(CharacterController2k openCharacterController,
RaycastHit hitInfo,
Vector3 directionMoved,
float distanceMoved)
{
collider = hitInfo.collider;
controller = openCharacterController;
gameObject = hitInfo.collider.gameObject;
moveDirection = directionMoved;
moveLength = distanceMoved;
normal = hitInfo.normal;
point = hitInfo.point;
rigidbody = hitInfo.rigidbody;
transform = hitInfo.transform;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2bce0b825e3445f3b49647a68f0f85ab
timeCreated: 1584448919

View File

@ -0,0 +1,26 @@
// CharacterController2k is based on Unity's OpenCharacterController, modified by vis2k, all rights reserved.
//
// -------------------------------------------------------------------------------------------------------------
// Original License from: https://github.com/Unity-Technologies/Standard-Assets-Characters:
// Licensed under the Unity Companion License for Unity-dependent projects--see Unity Companion License.
// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions.
//
using UnityEngine;
namespace Controller2k
{
public static class Extensions
{
// Is floatA equal to zero? Takes floating point inaccuracy into account, by using Epsilon.
public static bool IsEqualToZero(this float floatA)
{
return Mathf.Abs(floatA) < Mathf.Epsilon;
}
// Is floatA not equal to zero? Takes floating point inaccuracy into account, by using Epsilon.
public static bool NotEqualToZero(this float floatA)
{
return Mathf.Abs(floatA) > Mathf.Epsilon;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60075d32bcb8144eb8ac8b9a5f0964fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,55 @@
using UnityEngine;
namespace Controller2k
{
public static class Helpers
{
// Get the top sphere's world position.
public static Vector3 GetTopSphereWorldPosition(Vector3 position, Vector3 transformedCenter, float scaledRadius, float scaledHeight)
{
Vector3 sphereOffsetY = Vector3.up * (scaledHeight / 2.0f - scaledRadius);
return position + transformedCenter + sphereOffsetY;
}
// added to simulate collision checks for CanSetHeight/Center
// TODO can probably get rid of it and use the above function with proper parameters
public static Vector3 GetTopSphereWorldPositionSimulated(Transform transform, Vector3 center, float scaledRadius, float height)
{
float scaledHeight = height * transform.lossyScale.y;
Vector3 transformedCenter = transform.TransformVector(center);
return GetTopSphereWorldPosition(transform.position, transformedCenter, scaledRadius, scaledHeight);
}
// Get the bottom sphere's world position.
public static Vector3 GetBottomSphereWorldPosition(Vector3 position, Vector3 transformedCenter, float scaledRadius, float scaledHeight)
{
Vector3 sphereOffsetY = Vector3.up * (scaledHeight / 2.0f - scaledRadius);
return position + transformedCenter - sphereOffsetY;
}
// added to simulate collision checks for CanSetHeight/Center
// TODO can probably get rid of it and use the above function with proper parameters
public static Vector3 GetBottomSphereWorldPositionSimulated(Transform transform, Vector3 center, float scaledRadius, float height)
{
float scaledHeight = height * transform.lossyScale.y;
Vector3 transformedCenter = transform.TransformVector(center);
return GetBottomSphereWorldPosition(transform.position, transformedCenter, scaledRadius, scaledHeight);
}
// Calculate a new center if the height changes and preserve the foot position.
public static Vector3 CalculateCenterWithSameFootPosition(Vector3 center, float height, float newHeight, float skinWidth)
{
float localFootY = center.y - (height / 2.0f + skinWidth);
float newCenterY = localFootY + (newHeight / 2.0f + skinWidth);
return new Vector3(center.x, newCenterY, center.z);
}
// Is the movement vector almost zero (i.e. very small)?
public static bool IsMoveVectorAlmostZero(Vector3 moveVector, float smallThreshold)
{
return Mathf.Abs(moveVector.x) <= smallThreshold &&
Mathf.Abs(moveVector.y) <= smallThreshold &&
Mathf.Abs(moveVector.z) <= smallThreshold;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5f775b01ec9694dd48d4f0fb917bae6a
timeCreated: 1584448919

View File

@ -0,0 +1,24 @@
using UnityEngine;
namespace Controller2k
{
// A vector used by the OpenCharacterController.
public struct MoveVector
{
// The move vector.
// Note: This gets used up during the move loop, so will be zero by the end of the loop.
public Vector3 moveVector;
// Can the movement slide along obstacles?
public bool canSlide;
// Constructor.
// newMoveVector: The move vector.
// newCanSlide: Can the movement slide along obstacles?
public MoveVector(Vector3 newMoveVector, bool newCanSlide = true)
{
moveVector = newMoveVector;
canSlide = newCanSlide;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f2e60d0f4bf94ed5a2dc010f693c75e6
timeCreated: 1584449049

View File

@ -0,0 +1,97 @@
using UnityEngine;
namespace Controller2k
{
// Stuck info and logic used by the OpenCharacterController.
public class StuckInfo
{
// For keeping track of the character's position, to determine when the character gets stuck.
Vector3? stuckPosition;
// Count how long the character is in the same position.
int stuckPositionCount;
// If character's position does not change by more than this amount then we assume the character is stuck.
const float k_StuckDistance = 0.001f;
// If character collided this number of times during the movement loop then test if character is stuck by examining the position
const int k_HitCountForStuck = 6;
// Assume character is stuck if the position is the same for longer than this number of loop iterations
const int k_MaxStuckPositionCount = 1;
// Is the character stuck in the current move loop iteration?
public bool isStuck;
// Count the number of collisions during movement, to determine when the character gets stuck.
public int hitCount;
// Called when the move loop starts.
public void OnMoveLoop()
{
hitCount = 0;
stuckPositionCount = 0;
stuckPosition = null;
isStuck = false;
}
// Is the character stuck during the movement loop (e.g. bouncing between 2 or more colliders)?
// characterPosition: The character's position.
// currentMoveVector: Current move vector.
// originalMoveVector: Original move vector.
public bool UpdateStuck(Vector3 characterPosition, Vector3 currentMoveVector,
Vector3 originalMoveVector)
{
// First test
if (!isStuck)
{
// From Quake2: "if velocity is against the original velocity, stop dead to avoid tiny occilations in sloping corners"
if (currentMoveVector.sqrMagnitude.NotEqualToZero() &&
Vector3.Dot(currentMoveVector, originalMoveVector) <= 0.0f)
{
isStuck = true;
}
}
// Second test
if (!isStuck)
{
// Test if collided and while position remains the same
if (hitCount < k_HitCountForStuck)
{
return false;
}
if (stuckPosition == null)
{
stuckPosition = characterPosition;
}
else if (Vector3.Distance(stuckPosition.Value, characterPosition) <= k_StuckDistance)
{
stuckPositionCount++;
if (stuckPositionCount > k_MaxStuckPositionCount)
{
isStuck = true;
}
}
else
{
stuckPositionCount = 0;
stuckPosition = null;
}
}
if (isStuck)
{
isStuck = false;
hitCount = 0;
stuckPositionCount = 0;
stuckPosition = null;
return true;
}
return false;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fed936502da948c4b94c434014c8852f
timeCreated: 1584449202