移除ECM2
This commit is contained in:
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e410a670998601e4c86e40c34747c170
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b4ae63dacfed40dd8a3675e13b58068c
|
|
||||||
timeCreated: 1702783925
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Editor
|
|
||||||
{
|
|
||||||
public static class CharacterFactoryEditor
|
|
||||||
{
|
|
||||||
private const string PATH = "GameObject/ECM2/";
|
|
||||||
private const int PRIORITY = 1;
|
|
||||||
|
|
||||||
private static void InitPhysicsBody(GameObject go)
|
|
||||||
{
|
|
||||||
Rigidbody rb = go.GetComponent<Rigidbody>();
|
|
||||||
|
|
||||||
rb.linearDamping = 0.0f;
|
|
||||||
rb.angularDamping = 0.0f;
|
|
||||||
rb.useGravity = false;
|
|
||||||
rb.isKinematic = true;
|
|
||||||
rb.interpolation = RigidbodyInterpolation.Interpolate;
|
|
||||||
|
|
||||||
CapsuleCollider capsuleCollider = go.GetComponent<CapsuleCollider>();
|
|
||||||
|
|
||||||
capsuleCollider.center = new Vector3(0f, 1f, 0f);
|
|
||||||
capsuleCollider.radius = 0.5f;
|
|
||||||
capsuleCollider.height = 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem(PATH + "Character", false, PRIORITY)]
|
|
||||||
public static void CreateCharacter()
|
|
||||||
{
|
|
||||||
// Create an initialize a new Character GameObject
|
|
||||||
|
|
||||||
GameObject go = new GameObject("Character", typeof(Rigidbody), typeof(CapsuleCollider),
|
|
||||||
typeof(CharacterMovement), typeof(Character));
|
|
||||||
|
|
||||||
InitPhysicsBody(go);
|
|
||||||
|
|
||||||
// Focus the newly created character
|
|
||||||
|
|
||||||
Undo.RegisterCreatedObjectUndo(go, "Create " + go.name);
|
|
||||||
|
|
||||||
Selection.activeGameObject = go;
|
|
||||||
SceneView.FrameLastActiveSceneView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 229efc90fc94436ca2b1a73d23c044c6
|
|
||||||
timeCreated: 1702783950
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f9f3fcc8c4084496b897827d8e50634a
|
|
||||||
timeCreated: 1700450016
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 475ff761b0b75d14db323dd54effdaac
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4c24b37cf05649248a32b248a93eb05d
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 902a39e6598617c4596fd0bbc3ff7667
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57066912f8758f14b9bf7d2ece477e69
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 112000000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,117 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ac5ca879376bdb94e9f4867550fde697
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 13
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 1
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
flipGreenChannel: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
ignoreMipmapLimit: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 1
|
|
||||||
seamlessCubemap: 1
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 2
|
|
||||||
aniso: 0
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 1
|
|
||||||
wrapV: 1
|
|
||||||
wrapW: 1
|
|
||||||
nPOTScale: 1
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 0
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 0
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 0
|
|
||||||
textureShape: 2
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
swizzle: 50462976
|
|
||||||
cookieLightType: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 100
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
customData:
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID:
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
spriteCustomMetadata:
|
|
||||||
entries: []
|
|
||||||
nameFileIdTable: {}
|
|
||||||
mipmapLimitGroupName:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2fe07f4fb0c44cf9a8cb190a16e0c4e8
|
|
||||||
timeCreated: 1700523469
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ecf6744d31b373840925fd4dbd4cbf18
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 82dc065f9f6f4cb4953fe304639ea0ea
|
|
||||||
timeCreated: 1700707754
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using ECM2.Examples.FirstPerson;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.FirstPersonFly
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Regular First Person Character Input. Shows how to handle movement while flying.
|
|
||||||
/// In this case, we allow to fly towards our view direction, allowing to freely move through the air.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class FirstPersonFlyInput : FirstPersonInput
|
|
||||||
{
|
|
||||||
protected override void HandleInput()
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.HandleInput();
|
|
||||||
|
|
||||||
if (character.IsFlying())
|
|
||||||
{
|
|
||||||
// Movement when Flying
|
|
||||||
|
|
||||||
Vector2 movementInput = GetMovementInput();
|
|
||||||
Vector3 movementDirection = Vector3.zero;
|
|
||||||
|
|
||||||
// Strafe
|
|
||||||
|
|
||||||
movementDirection += character.GetRightVector() * movementInput.x;
|
|
||||||
|
|
||||||
// Forward, along camera view direction (if any) or along character's forward if camera not found
|
|
||||||
|
|
||||||
Vector3 forward = character.camera
|
|
||||||
? character.cameraTransform.forward
|
|
||||||
: character.GetForwardVector();
|
|
||||||
|
|
||||||
movementDirection += forward * movementInput.y;
|
|
||||||
|
|
||||||
// Vertical movement
|
|
||||||
|
|
||||||
if (character.jumpInputPressed)
|
|
||||||
movementDirection += Vector3.up;
|
|
||||||
|
|
||||||
character.SetMovementDirection(movementDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: cbbf3b9b979aa9d46901c3742b3c1230
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.FirstPersonFly
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example shows how to extend a Character (through composition) and use
|
|
||||||
/// its Flying movement mode to implement a fly ability.
|
|
||||||
///
|
|
||||||
/// Flying movement mode needs to be manually enabled / disabled as needed.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class FlyAbility : MonoBehaviour
|
|
||||||
{
|
|
||||||
public bool canEverFly = true;
|
|
||||||
|
|
||||||
private Character _character;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the Character is able to fly in its current state.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
private bool IsFlyAllowed()
|
|
||||||
{
|
|
||||||
return canEverFly && _character.IsFalling();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the character should enter flying movement mode.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual bool CanFly()
|
|
||||||
{
|
|
||||||
bool isFlyAllowed = IsFlyAllowed();
|
|
||||||
|
|
||||||
if (isFlyAllowed)
|
|
||||||
{
|
|
||||||
// If Fly is allowed, determine if is falling down otherwise its a jump!
|
|
||||||
|
|
||||||
Vector3 worldUp = -_character.GetGravityDirection();
|
|
||||||
float verticalSpeed = Vector3.Dot(_character.GetVelocity(), worldUp);
|
|
||||||
|
|
||||||
isFlyAllowed = verticalSpeed < 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isFlyAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCollided(ref CollisionResult collisionResult)
|
|
||||||
{
|
|
||||||
// If flying and collided with walkable ground, exit flying state.
|
|
||||||
// I.e: Change to Falling movement mode as this is managed based on grounding status.
|
|
||||||
|
|
||||||
if (_character.IsFlying() && collisionResult.isWalkable)
|
|
||||||
_character.SetMovementMode(Character.MovementMode.Falling);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBeforeSimulationUpdated(float deltaTime)
|
|
||||||
{
|
|
||||||
// Attempts to enter Flying movement mode
|
|
||||||
|
|
||||||
bool isFlying = _character.IsFlying();
|
|
||||||
bool wantsToFly = _character.jumpInputPressed;
|
|
||||||
|
|
||||||
if (!isFlying && wantsToFly && CanFly())
|
|
||||||
_character.SetMovementMode(Character.MovementMode.Flying);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_character = GetComponent<Character>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_character.Collided += OnCollided;
|
|
||||||
_character.BeforeSimulationUpdated += OnBeforeSimulationUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
_character.Collided -= OnCollided;
|
|
||||||
_character.BeforeSimulationUpdated -= OnBeforeSimulationUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: bda31f3d5180a634f93709c79f028bce
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 815661453b364202904d788f5432336a
|
|
||||||
timeCreated: 1700523481
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5f6e4d053a8307d4c820c4452d96fc36
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 66684442958e47e4bcf3c569fe375813
|
|
||||||
timeCreated: 1700707789
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using ECM2.Examples.FirstPerson;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.FirstPersonSwim
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example shows how to handle movement while swimming.
|
|
||||||
/// Here, we allow to swim towards our view direction, allowing to freely move through the water.
|
|
||||||
///
|
|
||||||
/// Swimming is automatically enabled / disabled when Water Physics Volume is used,
|
|
||||||
/// otherwise it must be enabled / disabled as needed.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class FirstPersonSwimInput : FirstPersonInput
|
|
||||||
{
|
|
||||||
protected override void HandleInput()
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.HandleInput();
|
|
||||||
|
|
||||||
if (character.IsSwimming())
|
|
||||||
{
|
|
||||||
// Handle movement when swimming
|
|
||||||
|
|
||||||
// Strafe
|
|
||||||
|
|
||||||
Vector2 movementInput = GetMovementInput();
|
|
||||||
Vector3 movementDirection = Vector3.zero;
|
|
||||||
movementDirection += character.GetRightVector() * movementInput.x;
|
|
||||||
|
|
||||||
// Forward, along camera view direction (if any) or along character's forward if camera not found
|
|
||||||
|
|
||||||
Vector3 forward =
|
|
||||||
character.camera ? character.cameraTransform.forward : character.GetForwardVector();
|
|
||||||
|
|
||||||
movementDirection += forward * movementInput.y;
|
|
||||||
|
|
||||||
// Vertical movement
|
|
||||||
|
|
||||||
if (character.jumpInputPressed)
|
|
||||||
{
|
|
||||||
// Use immersion depth to check if we are at top of water line,
|
|
||||||
// if yes, jump of water
|
|
||||||
|
|
||||||
float depth = character.CalcImmersionDepth();
|
|
||||||
if (depth > 0.65f)
|
|
||||||
movementDirection += character.GetUpVector();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Jump out of water
|
|
||||||
|
|
||||||
character.SetMovementMode(Character.MovementMode.Falling);
|
|
||||||
character.LaunchCharacter(character.GetUpVector() * 9.0f, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
character.SetMovementDirection(movementDirection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 492ff1da6c6e3884bbc194a74442b56b
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d6f0ddb4d2c11864ebefcdf23c9f5b1e
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ba11ada392fd66943aa0802367e37654
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 800cd5310655eb943a19e700021158a6
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.FirstPerson
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example extends a Character (through inheritance), implementing a First Person control.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class FirstPersonCharacter : Character
|
|
||||||
{
|
|
||||||
[Tooltip("The first person camera parent.")]
|
|
||||||
public GameObject cameraParent;
|
|
||||||
|
|
||||||
private float _cameraPitch;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add input (affecting Yaw).
|
|
||||||
/// This is applied to the Character's rotation.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual void AddControlYawInput(float value)
|
|
||||||
{
|
|
||||||
if (value != 0.0f)
|
|
||||||
AddYawInput(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add input (affecting Pitch).
|
|
||||||
/// This is applied to the cameraParent's local rotation.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual void AddControlPitchInput(float value, float minPitch = -80.0f, float maxPitch = 80.0f)
|
|
||||||
{
|
|
||||||
if (value != 0.0f)
|
|
||||||
_cameraPitch = MathLib.ClampAngle(_cameraPitch + value, minPitch, maxPitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update cameraParent local rotation applying current _cameraPitch value.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void UpdateCameraParentRotation()
|
|
||||||
{
|
|
||||||
cameraParent.transform.localRotation = Quaternion.Euler(_cameraPitch, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void LateUpdate()
|
|
||||||
{
|
|
||||||
UpdateCameraParentRotation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected override void Reset()
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.Reset();
|
|
||||||
|
|
||||||
// Disable character's rotation,
|
|
||||||
// it is handled by the AddControlYawInput method
|
|
||||||
|
|
||||||
SetRotationMode(RotationMode.None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 713b3a549961cf64d88d9131fdc9be1a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using UnityEngine.InputSystem;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.FirstPerson
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// First person character input.
|
|
||||||
/// Extends the default CharacterInput component adding support for typical first person controls.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class FirstPersonInput : CharacterInput
|
|
||||||
{
|
|
||||||
[Space(15.0f)]
|
|
||||||
public bool invertLook = true;
|
|
||||||
[Tooltip("Look sensitivity")]
|
|
||||||
public Vector2 sensitivity = new Vector2(0.05f, 0.05f);
|
|
||||||
|
|
||||||
[Space(15.0f)]
|
|
||||||
[Tooltip("How far in degrees can you move the camera down.")]
|
|
||||||
public float minPitch = -80.0f;
|
|
||||||
[Tooltip("How far in degrees can you move the camera up.")]
|
|
||||||
public float maxPitch = 80.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cached FirstPersonCharacter.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public FirstPersonCharacter firstPersonCharacter { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Movement InputAction.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public InputAction lookInputAction { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Polls look InputAction (if any).
|
|
||||||
/// Return its current value or zero if no valid InputAction found.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public Vector2 GetLookInput()
|
|
||||||
{
|
|
||||||
return lookInputAction?.ReadValue<Vector2>() ?? Vector2.zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initialize player InputActions (if any).
|
|
||||||
/// E.g. Subscribe to input action events and enable input actions here.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected override void InitPlayerInput()
|
|
||||||
{
|
|
||||||
base.InitPlayerInput();
|
|
||||||
|
|
||||||
// Look input action (no handler, this is polled, e.g. GetLookInput())
|
|
||||||
|
|
||||||
lookInputAction = inputActionsAsset.FindAction("Look");
|
|
||||||
lookInputAction?.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Unsubscribe from input action events and disable input actions.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected override void DeinitPlayerInput()
|
|
||||||
{
|
|
||||||
base.DeinitPlayerInput();
|
|
||||||
|
|
||||||
// Unsubscribe from input action events and disable input actions
|
|
||||||
|
|
||||||
if (lookInputAction != null)
|
|
||||||
{
|
|
||||||
lookInputAction.Disable();
|
|
||||||
lookInputAction = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Awake()
|
|
||||||
{
|
|
||||||
base.Awake();
|
|
||||||
|
|
||||||
firstPersonCharacter = character as FirstPersonCharacter;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Start()
|
|
||||||
{
|
|
||||||
Cursor.lockState = CursorLockMode.Locked;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void HandleInput()
|
|
||||||
{
|
|
||||||
// Move
|
|
||||||
|
|
||||||
Vector2 movementInput = GetMovementInput();
|
|
||||||
|
|
||||||
Vector3 movementDirection = Vector3.zero;
|
|
||||||
|
|
||||||
movementDirection += Vector3.forward * movementInput.y;
|
|
||||||
movementDirection += Vector3.right * movementInput.x;
|
|
||||||
|
|
||||||
movementDirection =
|
|
||||||
movementDirection.relativeTo(firstPersonCharacter.cameraTransform, firstPersonCharacter.GetUpVector());
|
|
||||||
|
|
||||||
firstPersonCharacter.SetMovementDirection(movementDirection);
|
|
||||||
|
|
||||||
// Look
|
|
||||||
|
|
||||||
Vector2 lookInput = GetLookInput() * sensitivity;
|
|
||||||
|
|
||||||
firstPersonCharacter.AddControlYawInput(lookInput.x);
|
|
||||||
firstPersonCharacter.AddControlPitchInput(invertLook ? -lookInput.y : lookInput.y, minPitch, maxPitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ba598d44e33b26849a4d3d6005e49fd1
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 43bf17ba2afdabe47a7815ab3d6c2cd6
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e74b0d624806d3a44945b1bbb4524553
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 137e5ade8532c7b4bbcc84ad8d35487d
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Glide
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example shows how to extend a Character (through composition) implementing a Glide mechanic.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class GlideAbility : MonoBehaviour
|
|
||||||
{
|
|
||||||
public bool canEverGlide = true;
|
|
||||||
public float maxFallSpeedGliding = 1.0f;
|
|
||||||
|
|
||||||
private Character _character;
|
|
||||||
|
|
||||||
protected bool _glideInputPressed;
|
|
||||||
protected bool _isGliding;
|
|
||||||
|
|
||||||
public bool glideInputPressed => _glideInputPressed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is the Character gliding?
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual bool IsGliding()
|
|
||||||
{
|
|
||||||
return _isGliding;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request to start a glide.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual void Glide()
|
|
||||||
{
|
|
||||||
_glideInputPressed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request to stop gliding.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual void StopGliding()
|
|
||||||
{
|
|
||||||
_glideInputPressed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the character is able to perform a glide in its current state.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual bool IsGlideAllowed()
|
|
||||||
{
|
|
||||||
return canEverGlide && _character.IsFalling();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the character can perform a requested glide.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual bool CanGlide()
|
|
||||||
{
|
|
||||||
bool isGlideAllowed = IsGlideAllowed();
|
|
||||||
|
|
||||||
if (isGlideAllowed)
|
|
||||||
{
|
|
||||||
Vector3 worldUp = -_character.GetGravityDirection();
|
|
||||||
float verticalSpeed = Vector3.Dot(_character.GetVelocity(), worldUp);
|
|
||||||
|
|
||||||
isGlideAllowed = verticalSpeed < 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isGlideAllowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start / Stop a requested glide.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void CheckGlideInput()
|
|
||||||
{
|
|
||||||
if (!_isGliding && _glideInputPressed && CanGlide())
|
|
||||||
{
|
|
||||||
_isGliding = true;
|
|
||||||
_character.maxFallSpeed = maxFallSpeedGliding;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (_isGliding && (!_glideInputPressed || !CanGlide()))
|
|
||||||
{
|
|
||||||
_isGliding = false;
|
|
||||||
_character.maxFallSpeed = 40.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBeforeCharacterSimulationUpdated(float deltaTime)
|
|
||||||
{
|
|
||||||
CheckGlideInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_character = GetComponent<Character>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_character.BeforeSimulationUpdated += OnBeforeCharacterSimulationUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
_character.BeforeSimulationUpdated -= OnBeforeCharacterSimulationUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d97f3b8906b7417e88698c51eb7e04c8
|
|
||||||
timeCreated: 1700291875
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
using UnityEngine.InputSystem;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Glide
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extends default Character Input to handle GlideAbility Input.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class GlideInput : CharacterInput
|
|
||||||
{
|
|
||||||
private GlideAbility _glideAbility;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extend OnJump handler to add GlideAbility input support.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public override void OnJump(InputAction.CallbackContext context)
|
|
||||||
{
|
|
||||||
// Call base method implementation (handle jump)
|
|
||||||
|
|
||||||
base.OnJump(context);
|
|
||||||
|
|
||||||
if (context.started)
|
|
||||||
_glideAbility.Glide();
|
|
||||||
else if (context.canceled)
|
|
||||||
_glideAbility.StopGliding();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Awake()
|
|
||||||
{
|
|
||||||
base.Awake();
|
|
||||||
|
|
||||||
// Cache Glide Ability
|
|
||||||
|
|
||||||
_glideAbility = GetComponent<GlideAbility>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 49ae0493228344b5b3bdfc1bf5545e57
|
|
||||||
timeCreated: 1700292768
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: aa1a2b686f299e74e923e08fcae397f6
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f75d14915da71e7428ad9168e63a1789
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5be7a2664b8bb6b4c9d56b86dc8964c0
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,413 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Jump
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example shows how to extend a Character (through composition) implementing a jump ability.
|
|
||||||
/// This is the exact jump available in the Character class before v1.4.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class JumpAbility : MonoBehaviour
|
|
||||||
{
|
|
||||||
[Space(15f)]
|
|
||||||
[Tooltip("Is the character able to jump ?")]
|
|
||||||
[SerializeField]
|
|
||||||
private bool _canEverJump;
|
|
||||||
|
|
||||||
[Tooltip("Can jump while crouching ?")]
|
|
||||||
[SerializeField]
|
|
||||||
private bool _jumpWhileCrouching;
|
|
||||||
|
|
||||||
[Tooltip("The max number of jumps the Character can perform.")]
|
|
||||||
[SerializeField]
|
|
||||||
private int _jumpMaxCount;
|
|
||||||
|
|
||||||
[Tooltip("Initial velocity (instantaneous vertical velocity) when jumping.")]
|
|
||||||
[SerializeField]
|
|
||||||
private float _jumpImpulse;
|
|
||||||
|
|
||||||
[Tooltip("The maximum time (in seconds) to hold the jump. eg: Variable height jump.")]
|
|
||||||
[SerializeField]
|
|
||||||
private float _jumpMaxHoldTime;
|
|
||||||
|
|
||||||
[Tooltip("How early before hitting the ground you can trigger a jump (in seconds).")]
|
|
||||||
[SerializeField]
|
|
||||||
private float _jumpPreGroundedTime;
|
|
||||||
|
|
||||||
[Tooltip("How long after leaving the ground you can trigger a jump (in seconds).")]
|
|
||||||
[SerializeField]
|
|
||||||
private float _jumpPostGroundedTime;
|
|
||||||
|
|
||||||
private Character _character;
|
|
||||||
|
|
||||||
protected bool _jumpButtonPressed;
|
|
||||||
protected float _jumpButtonHeldDownTime;
|
|
||||||
protected float _jumpHoldTime;
|
|
||||||
protected int _jumpCount;
|
|
||||||
protected bool _isJumping;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is the character able to jump ?
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public bool canEverJump
|
|
||||||
{
|
|
||||||
get => _canEverJump;
|
|
||||||
set => _canEverJump = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Can jump while crouching ?
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public bool jumpWhileCrouching
|
|
||||||
{
|
|
||||||
get => _jumpWhileCrouching;
|
|
||||||
set => _jumpWhileCrouching = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The max number of jumps the Character can perform.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public int jumpMaxCount
|
|
||||||
{
|
|
||||||
get => _jumpMaxCount;
|
|
||||||
set => _jumpMaxCount = Mathf.Max(1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initial velocity (instantaneous vertical velocity) when jumping.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public float jumpImpulse
|
|
||||||
{
|
|
||||||
get => _jumpImpulse;
|
|
||||||
set => _jumpImpulse = Mathf.Max(0.0f, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The maximum time (in seconds) to hold the jump. eg: Variable height jump.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public float jumpMaxHoldTime
|
|
||||||
{
|
|
||||||
get => _jumpMaxHoldTime;
|
|
||||||
set => _jumpMaxHoldTime = Mathf.Max(0.0f, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How early before hitting the ground you can trigger a jump (in seconds).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public float jumpPreGroundedTime
|
|
||||||
{
|
|
||||||
get => _jumpPreGroundedTime;
|
|
||||||
set => _jumpPreGroundedTime = Mathf.Max(0.0f, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How long after leaving the ground you can trigger a jump (in seconds).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public float jumpPostGroundedTime
|
|
||||||
{
|
|
||||||
get => _jumpPostGroundedTime;
|
|
||||||
set => _jumpPostGroundedTime = Mathf.Max(0.0f, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True is _jumpButtonPressed is true, false otherwise.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public bool jumpButtonPressed => _jumpButtonPressed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is the time (in seconds) that the player has held the jump button.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public float jumpButtonHeldDownTime => _jumpButtonHeldDownTime;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tracks the current number of jumps performed.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public int jumpCount => _jumpCount;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is the time (in seconds) that the player has been holding the jump.
|
|
||||||
/// Eg: Variable height jump.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public float jumpHoldTime => _jumpHoldTime;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is the Character jumping ?
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual bool IsJumping()
|
|
||||||
{
|
|
||||||
return _isJumping;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start a jump.
|
|
||||||
/// Call this from an input event (such as a button 'down' event).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public void Jump()
|
|
||||||
{
|
|
||||||
_jumpButtonPressed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stop the Character from jumping.
|
|
||||||
/// Call this from an input event (such as a button 'up' event).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public void StopJumping()
|
|
||||||
{
|
|
||||||
// Input state
|
|
||||||
|
|
||||||
_jumpButtonPressed = false;
|
|
||||||
_jumpButtonHeldDownTime = 0.0f;
|
|
||||||
|
|
||||||
// Jump holding state
|
|
||||||
|
|
||||||
_isJumping = false;
|
|
||||||
_jumpHoldTime = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the current jump count.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual int GetJumpCount()
|
|
||||||
{
|
|
||||||
return _jumpCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the Character is able to perform the requested jump.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual bool CanJump()
|
|
||||||
{
|
|
||||||
// Is character even able to jump ?
|
|
||||||
|
|
||||||
if (!canEverJump)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Can jump while crouching ?
|
|
||||||
|
|
||||||
if (_character.IsCrouched() && !jumpWhileCrouching)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Cant jump if no jumps available
|
|
||||||
|
|
||||||
if (jumpMaxCount == 0 || _jumpCount >= jumpMaxCount)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Is fist jump ?
|
|
||||||
|
|
||||||
if (_jumpCount == 0)
|
|
||||||
{
|
|
||||||
// On first jump,
|
|
||||||
// can jump if is walking or is falling BUT withing post grounded time
|
|
||||||
|
|
||||||
bool canJump = _character.IsWalking() ||
|
|
||||||
_character.IsFalling() && jumpPostGroundedTime > 0.0f && _character.fallingTime < jumpPostGroundedTime;
|
|
||||||
|
|
||||||
// Missed post grounded time ?
|
|
||||||
|
|
||||||
if (_character.IsFalling() && !canJump)
|
|
||||||
{
|
|
||||||
// Missed post grounded time,
|
|
||||||
// can jump if have any 'in-air' jumps but the first jump counts as the in-air jump
|
|
||||||
|
|
||||||
canJump = jumpMaxCount > 1;
|
|
||||||
if (canJump)
|
|
||||||
_jumpCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return canJump;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In air jump conditions...
|
|
||||||
|
|
||||||
return _character.IsFalling();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines the jump impulse vector.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual Vector3 CalcJumpImpulse()
|
|
||||||
{
|
|
||||||
Vector3 worldUp = -_character.GetGravityDirection();
|
|
||||||
|
|
||||||
float verticalSpeed = Vector3.Dot(_character.GetVelocity(), worldUp);
|
|
||||||
float actualJumpImpulse = Mathf.Max(verticalSpeed, jumpImpulse);
|
|
||||||
|
|
||||||
return worldUp * actualJumpImpulse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to perform a requested jump.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void DoJump(float deltaTime)
|
|
||||||
{
|
|
||||||
// Update held down timer
|
|
||||||
|
|
||||||
if (_jumpButtonPressed)
|
|
||||||
_jumpButtonHeldDownTime += deltaTime;
|
|
||||||
|
|
||||||
// Wants to jump and not already jumping..
|
|
||||||
|
|
||||||
if (_jumpButtonPressed && !IsJumping())
|
|
||||||
{
|
|
||||||
// If jumpPreGroundedTime is enabled,
|
|
||||||
// allow to jump only if held down time is less than tolerance
|
|
||||||
|
|
||||||
if (jumpPreGroundedTime > 0.0f)
|
|
||||||
{
|
|
||||||
bool canJump = _jumpButtonHeldDownTime <= jumpPreGroundedTime;
|
|
||||||
if (!canJump)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can perform the requested jump ?
|
|
||||||
|
|
||||||
if (CanJump())
|
|
||||||
{
|
|
||||||
// Jump!
|
|
||||||
|
|
||||||
_character.SetMovementMode(Character.MovementMode.Falling);
|
|
||||||
|
|
||||||
_character.PauseGroundConstraint();
|
|
||||||
_character.LaunchCharacter(CalcJumpImpulse(), true);
|
|
||||||
|
|
||||||
_jumpCount++;
|
|
||||||
_isJumping = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handle jumping state.
|
|
||||||
/// Eg: check input, perform jump hold (jumpMaxHoldTime > 0), etc.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void Jumping(float deltaTime)
|
|
||||||
{
|
|
||||||
// Is character allowed to jump ?
|
|
||||||
|
|
||||||
if (!canEverJump)
|
|
||||||
{
|
|
||||||
// If not allowed but was jumping, stop jump
|
|
||||||
|
|
||||||
if (IsJumping())
|
|
||||||
StopJumping();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check jump input state and attempts to do the requested jump
|
|
||||||
|
|
||||||
DoJump(deltaTime);
|
|
||||||
|
|
||||||
// Perform jump hold, applies an opposite gravity force proportional to _jumpHoldTime.
|
|
||||||
|
|
||||||
if (IsJumping() && _jumpButtonPressed && jumpMaxHoldTime > 0.0f && _jumpHoldTime < jumpMaxHoldTime)
|
|
||||||
{
|
|
||||||
Vector3 actualGravity = _character.GetGravityVector();
|
|
||||||
|
|
||||||
float actualGravityMagnitude = actualGravity.magnitude;
|
|
||||||
Vector3 actualGravityDirection = actualGravityMagnitude > 0.0f
|
|
||||||
? actualGravity / actualGravityMagnitude
|
|
||||||
: Vector3.zero;
|
|
||||||
|
|
||||||
float jumpProgress = Mathf.InverseLerp(0.0f, jumpMaxHoldTime, _jumpHoldTime);
|
|
||||||
float proportionalForce = Mathf.LerpUnclamped(actualGravityMagnitude, 0.0f, jumpProgress);
|
|
||||||
|
|
||||||
Vector3 proportionalJumpForce = -actualGravityDirection * proportionalForce;
|
|
||||||
_character.AddForce(proportionalJumpForce);
|
|
||||||
|
|
||||||
_jumpHoldTime += deltaTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnMovementModeChanged(Character.MovementMode prevMovementMode, int prevCustomMode)
|
|
||||||
{
|
|
||||||
if (_character.IsWalking())
|
|
||||||
_jumpCount = 0;
|
|
||||||
else if (_character.IsFlying() || _character.IsSwimming())
|
|
||||||
StopJumping();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void Reset()
|
|
||||||
{
|
|
||||||
_canEverJump = true;
|
|
||||||
_jumpWhileCrouching = true;
|
|
||||||
_jumpMaxCount = 1;
|
|
||||||
_jumpImpulse = 5.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnValidate()
|
|
||||||
{
|
|
||||||
jumpMaxCount = _jumpMaxCount;
|
|
||||||
jumpImpulse = _jumpImpulse;
|
|
||||||
jumpMaxHoldTime = _jumpMaxHoldTime;
|
|
||||||
jumpPreGroundedTime = _jumpPreGroundedTime;
|
|
||||||
jumpPostGroundedTime = _jumpPostGroundedTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void Awake()
|
|
||||||
{
|
|
||||||
_character = GetComponent<Character>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void OnEnable()
|
|
||||||
{
|
|
||||||
_character.MovementModeChanged += OnMovementModeChanged;
|
|
||||||
_character.BeforeSimulationUpdated += Jumping;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void OnDisable()
|
|
||||||
{
|
|
||||||
_character.BeforeSimulationUpdated -= Jumping;
|
|
||||||
_character.MovementModeChanged -= OnMovementModeChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If overriden, base method MUST be called.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void Start()
|
|
||||||
{
|
|
||||||
// Disable Character built-in jump
|
|
||||||
|
|
||||||
_character.canEverJump = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 06597227e58abd64eb2b11f0a43d4219
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
using UnityEngine.InputSystem;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Jump
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extends default Character Input to handle JumpAbility Input.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class JumpInput : CharacterInput
|
|
||||||
{
|
|
||||||
// The jump ability
|
|
||||||
|
|
||||||
private JumpAbility _jumpAbility;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extend OnJump handler to manage JumpAbility input.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public override void OnJump(InputAction.CallbackContext context)
|
|
||||||
{
|
|
||||||
if (context.started)
|
|
||||||
_jumpAbility.Jump();
|
|
||||||
else if (context.canceled)
|
|
||||||
_jumpAbility.StopJumping();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Awake()
|
|
||||||
{
|
|
||||||
base.Awake();
|
|
||||||
|
|
||||||
// Cache JumpAbility
|
|
||||||
|
|
||||||
_jumpAbility = GetComponent<JumpAbility>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3b75fe96fbf5426a80316e1303c9fa5c
|
|
||||||
timeCreated: 1700900486
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4769c4722c8844c49d187dbe2b9c7bad
|
|
||||||
timeCreated: 1700523532
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e2251171a89ad034d9cdb694d2cc700f
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 593d3397361c48ab9f2a4688ec660199
|
|
||||||
timeCreated: 1700524424
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Ladders
|
|
||||||
{
|
|
||||||
public sealed class Ladder : MonoBehaviour
|
|
||||||
{
|
|
||||||
#region EDITOR EXPOSED FIELDS
|
|
||||||
|
|
||||||
[Header("Ladder Path")]
|
|
||||||
public float PathLength = 10.0f;
|
|
||||||
public Vector3 PathOffset = new Vector3(0f, 0f, -0.5f);
|
|
||||||
|
|
||||||
[Header("Anchor Points")]
|
|
||||||
public Transform TopPoint;
|
|
||||||
public Transform BottomPoint;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region PROPERTIES
|
|
||||||
|
|
||||||
public Vector3 bottomAnchorPoint => transform.position + transform.TransformVector(PathOffset);
|
|
||||||
|
|
||||||
public Vector3 topAnchorPoint => bottomAnchorPoint + transform.up * PathLength;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region METHODS
|
|
||||||
|
|
||||||
public Vector3 ClosestPointOnPath(Vector3 position, out float pathPosition)
|
|
||||||
{
|
|
||||||
Vector3 path = topAnchorPoint - bottomAnchorPoint;
|
|
||||||
Vector3 pathToPoint = position - bottomAnchorPoint;
|
|
||||||
|
|
||||||
float height = Vector3.Dot(pathToPoint, path.normalized);
|
|
||||||
|
|
||||||
if (height > 0.0f)
|
|
||||||
{
|
|
||||||
// If we are below top point
|
|
||||||
|
|
||||||
if (height <= path.magnitude)
|
|
||||||
{
|
|
||||||
pathPosition = 0;
|
|
||||||
return bottomAnchorPoint + path.normalized * height;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are higher than top point
|
|
||||||
|
|
||||||
pathPosition = height - path.magnitude;
|
|
||||||
return topAnchorPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Below bottom point
|
|
||||||
|
|
||||||
pathPosition = height;
|
|
||||||
return bottomAnchorPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region MONOBEHAVIOUR
|
|
||||||
|
|
||||||
private void OnDrawGizmos()
|
|
||||||
{
|
|
||||||
Gizmos.color = Color.yellow;
|
|
||||||
Gizmos.DrawLine(bottomAnchorPoint, topAnchorPoint);
|
|
||||||
|
|
||||||
if (BottomPoint == null || TopPoint == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Gizmos.DrawWireCube(BottomPoint.position, Vector3.one * 0.25f);
|
|
||||||
Gizmos.DrawWireCube(TopPoint.position, Vector3.one * 0.25f);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: eaeb4b7f9b0647b4ba93dc7f142b09f6
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,287 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Ladders
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example shows how to extend a Character (through composition) adding a custom movement mode.
|
|
||||||
/// Here we implement a ladder climbing ability using a Climbing custom movement mode.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class LadderClimbAbility : MonoBehaviour
|
|
||||||
{
|
|
||||||
public enum CustomMovementMode
|
|
||||||
{
|
|
||||||
Climbing = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ClimbingState
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Grabbing,
|
|
||||||
Grabbed,
|
|
||||||
Releasing
|
|
||||||
}
|
|
||||||
|
|
||||||
public float climbingSpeed = 5.0f;
|
|
||||||
public float grabbingTime = 0.25f;
|
|
||||||
|
|
||||||
public LayerMask ladderMask;
|
|
||||||
|
|
||||||
private Character _character;
|
|
||||||
|
|
||||||
private Ladder _activeLadder;
|
|
||||||
private float _ladderPathPosition;
|
|
||||||
|
|
||||||
private Vector3 _ladderStartPosition;
|
|
||||||
private Vector3 _ladderTargetPosition;
|
|
||||||
|
|
||||||
private Quaternion _ladderStartRotation;
|
|
||||||
private Quaternion _ladderTargetRotation;
|
|
||||||
|
|
||||||
private float _ladderTime;
|
|
||||||
|
|
||||||
private ClimbingState _climbingState;
|
|
||||||
|
|
||||||
private Character.RotationMode _previousRotationMode;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if the Character is in Climbing custom movement mode, false otherwise.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public bool IsClimbing()
|
|
||||||
{
|
|
||||||
bool isClimbing = _character.movementMode == Character.MovementMode.Custom &&
|
|
||||||
_character.customMovementMode == (int)CustomMovementMode.Climbing;
|
|
||||||
|
|
||||||
return isClimbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the Character is able to climb.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
private bool CanClimb()
|
|
||||||
{
|
|
||||||
// Do not allow to climb if crouching
|
|
||||||
|
|
||||||
if (_character.IsCrouched())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Attempt to find a ladder
|
|
||||||
|
|
||||||
CharacterMovement characterMovement = _character.characterMovement;
|
|
||||||
var overlappedColliders =
|
|
||||||
characterMovement.OverlapTest(ladderMask, QueryTriggerInteraction.Collide, out int overlapCount);
|
|
||||||
|
|
||||||
if (overlapCount == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Is a ladder ?
|
|
||||||
|
|
||||||
if (!overlappedColliders[0].TryGetComponent(out Ladder ladder))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Found a ladder, make it active ladder and return
|
|
||||||
|
|
||||||
_activeLadder = ladder;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start a climb.
|
|
||||||
/// Call this from an input event (such as a button 'down' event).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public void Climb()
|
|
||||||
{
|
|
||||||
if (IsClimbing() || !CanClimb())
|
|
||||||
return;
|
|
||||||
|
|
||||||
_character.SetMovementMode(Character.MovementMode.Custom, (int) CustomMovementMode.Climbing);
|
|
||||||
|
|
||||||
_ladderStartPosition = _character.GetPosition();
|
|
||||||
_ladderTargetPosition = _activeLadder.ClosestPointOnPath(_ladderStartPosition, out _ladderPathPosition);
|
|
||||||
|
|
||||||
_ladderStartRotation = _character.GetRotation();
|
|
||||||
_ladderTargetRotation = _activeLadder.transform.rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stop the Character from climbing.
|
|
||||||
/// Call this from an input event (such as a button 'up' event).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public void StopClimbing()
|
|
||||||
{
|
|
||||||
if (!IsClimbing() || _climbingState != ClimbingState.Grabbed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_climbingState = ClimbingState.Releasing;
|
|
||||||
|
|
||||||
_ladderStartPosition = _character.GetPosition();
|
|
||||||
_ladderStartRotation = _character.GetRotation();
|
|
||||||
|
|
||||||
_ladderTargetPosition = _ladderStartPosition;
|
|
||||||
_ladderTargetRotation = _activeLadder.BottomPoint.rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Perform climbing movement.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
private void ClimbingMovementMode(float deltaTime)
|
|
||||||
{
|
|
||||||
Vector3 velocity = Vector3.zero;
|
|
||||||
|
|
||||||
switch (_climbingState)
|
|
||||||
{
|
|
||||||
case ClimbingState.Grabbing:
|
|
||||||
case ClimbingState.Releasing:
|
|
||||||
{
|
|
||||||
_ladderTime += deltaTime;
|
|
||||||
|
|
||||||
if (_ladderTime <= grabbingTime)
|
|
||||||
{
|
|
||||||
Vector3 interpolatedPosition = Vector3.Lerp(_ladderStartPosition, _ladderTargetPosition, _ladderTime / grabbingTime);
|
|
||||||
|
|
||||||
velocity = (interpolatedPosition - transform.position) / deltaTime;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If target has been reached, change ladder phase
|
|
||||||
|
|
||||||
_ladderTime = 0.0f;
|
|
||||||
|
|
||||||
if (_climbingState == ClimbingState.Grabbing )
|
|
||||||
{
|
|
||||||
// Switch to ladder climb phase
|
|
||||||
|
|
||||||
_climbingState = ClimbingState.Grabbed;
|
|
||||||
}
|
|
||||||
else if (_climbingState == ClimbingState.Releasing)
|
|
||||||
{
|
|
||||||
// Exit climbing state (change to falling movement mode)
|
|
||||||
|
|
||||||
_character.SetMovementMode(Character.MovementMode.Falling);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ClimbingState.Grabbed:
|
|
||||||
{
|
|
||||||
// Get the path position from character's current position
|
|
||||||
|
|
||||||
_activeLadder.ClosestPointOnPath(_character.GetPosition(), out _ladderPathPosition);
|
|
||||||
|
|
||||||
if (Mathf.Abs(_ladderPathPosition) < 0.05f)
|
|
||||||
{
|
|
||||||
// Move the character along the ladder path
|
|
||||||
|
|
||||||
Vector3 movementInput = _character.GetMovementDirection();
|
|
||||||
|
|
||||||
velocity = _activeLadder.transform.up * (movementInput.z * climbingSpeed);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If reached on of the ladder path extremes, change to releasing phase
|
|
||||||
|
|
||||||
_climbingState = ClimbingState.Releasing;
|
|
||||||
|
|
||||||
_ladderStartPosition = _character.GetPosition();
|
|
||||||
_ladderStartRotation = _character.GetRotation();
|
|
||||||
|
|
||||||
if (_ladderPathPosition > 0.0f)
|
|
||||||
{
|
|
||||||
// Above ladder path top point
|
|
||||||
|
|
||||||
_ladderTargetPosition = _activeLadder.TopPoint.position;
|
|
||||||
_ladderTargetRotation = _activeLadder.TopPoint.rotation;
|
|
||||||
}
|
|
||||||
else if (_ladderPathPosition < 0.0f)
|
|
||||||
{
|
|
||||||
// Below ladder path bottom point
|
|
||||||
|
|
||||||
_ladderTargetPosition = _activeLadder.BottomPoint.position;
|
|
||||||
_ladderTargetRotation = _activeLadder.BottomPoint.rotation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update character's velocity
|
|
||||||
|
|
||||||
_character.SetVelocity(velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMovementModeChanged(Character.MovementMode prevMovementMode, int prevCustomMovementMode)
|
|
||||||
{
|
|
||||||
// Enter Climbing movement mode
|
|
||||||
|
|
||||||
if (IsClimbing())
|
|
||||||
{
|
|
||||||
_climbingState = ClimbingState.Grabbing;
|
|
||||||
|
|
||||||
_character.StopJumping();
|
|
||||||
|
|
||||||
_character.EnableGroundConstraint(false);
|
|
||||||
|
|
||||||
_previousRotationMode = _character.rotationMode;
|
|
||||||
_character.SetRotationMode(Character.RotationMode.Custom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit Climbing movement mode
|
|
||||||
|
|
||||||
bool wasClimbing = prevMovementMode == Character.MovementMode.Custom &&
|
|
||||||
prevCustomMovementMode == (int)CustomMovementMode.Climbing;
|
|
||||||
|
|
||||||
if (wasClimbing)
|
|
||||||
{
|
|
||||||
_climbingState = ClimbingState.None;
|
|
||||||
|
|
||||||
_character.EnableGroundConstraint(true);
|
|
||||||
_character.SetRotationMode(_previousRotationMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCustomMovementModeUpdated(float deltaTime)
|
|
||||||
{
|
|
||||||
if (IsClimbing())
|
|
||||||
ClimbingMovementMode(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCustomRotationModeUpdated(float deltaTime)
|
|
||||||
{
|
|
||||||
if (IsClimbing() && (_climbingState == ClimbingState.Grabbing || _climbingState == ClimbingState.Releasing))
|
|
||||||
{
|
|
||||||
Quaternion rotation =
|
|
||||||
Quaternion.Slerp(_ladderStartRotation, _ladderTargetRotation, _ladderTime / grabbingTime);
|
|
||||||
|
|
||||||
_character.SetRotation(rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_character = GetComponent<Character>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_character.MovementModeChanged += OnMovementModeChanged;
|
|
||||||
_character.CustomMovementModeUpdated += OnCustomMovementModeUpdated;
|
|
||||||
_character.CustomRotationModeUpdated += OnCustomRotationModeUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
_character.MovementModeChanged -= OnMovementModeChanged;
|
|
||||||
_character.CustomMovementModeUpdated -= OnCustomMovementModeUpdated;
|
|
||||||
_character.CustomRotationModeUpdated -= OnCustomRotationModeUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5ef7d6f6890f479fac1591d410e31408
|
|
||||||
timeCreated: 1700524463
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
using UnityEngine.InputSystem;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Ladders
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Extends default Character Input to handle LadderClimbInput Input.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class LadderClimbInput : CharacterInput
|
|
||||||
{
|
|
||||||
private LadderClimbAbility _ladderClimbAbility;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interact InputAction.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public InputAction interactInputAction { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Jump InputAction handler.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public virtual void OnInteract(InputAction.CallbackContext context)
|
|
||||||
{
|
|
||||||
if (context.started)
|
|
||||||
_ladderClimbAbility.Climb();
|
|
||||||
else if (context.canceled)
|
|
||||||
_ladderClimbAbility.StopClimbing();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void InitPlayerInput()
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.InitPlayerInput();
|
|
||||||
|
|
||||||
// Setup Interact input action handlers
|
|
||||||
|
|
||||||
interactInputAction = inputActionsAsset.FindAction("Interact");
|
|
||||||
if (interactInputAction != null)
|
|
||||||
{
|
|
||||||
interactInputAction.started += OnInteract;
|
|
||||||
interactInputAction.canceled += OnInteract;
|
|
||||||
|
|
||||||
interactInputAction.Enable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DeinitPlayerInput()
|
|
||||||
{
|
|
||||||
base.DeinitPlayerInput();
|
|
||||||
|
|
||||||
// Unsubscribe from input action events and disable input actions
|
|
||||||
|
|
||||||
if (interactInputAction != null)
|
|
||||||
{
|
|
||||||
interactInputAction.started -= OnInteract;
|
|
||||||
interactInputAction.canceled -= OnInteract;
|
|
||||||
|
|
||||||
interactInputAction.Disable();
|
|
||||||
interactInputAction = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Awake()
|
|
||||||
{
|
|
||||||
base.Awake();
|
|
||||||
|
|
||||||
// Cache Ladder Climb Ability
|
|
||||||
|
|
||||||
_ladderClimbAbility = GetComponent<LadderClimbAbility>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 57e07038965948caa8713a162db0f2be
|
|
||||||
timeCreated: 1700530516
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8dc639f37a2842f4797f45420d642695
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1d9c687e966e32d43a70620826011878
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 491c3a228ce9f5240bba52a7a7803b4c
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: da38947f7e566784b87c8bd65d208713
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 632c6e9af7bb79949a32cabf0120ff1d
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2f4c17cba879bdb4c9259964863b47be
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c375cc69af33f7445ba348c9296d1651
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 078686a70f118ab45aef26d1a863eb79
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2bff2fd571e446343a27d8456cf58553
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e226eaad11f756648b790d950a5c1d66
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b6503c5dd5b759f4682c6790728822ff
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 702cd3842e1f48b78516f11a721bb0bb
|
|
||||||
timeCreated: 1700621484
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.OrientToGround
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example extends a Character (through composition) to adjust a Character's rotation
|
|
||||||
/// to follow a 'terrain' contour.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class CharacterOrientToGround : MonoBehaviour, IColliderFilter
|
|
||||||
{
|
|
||||||
public float maxSlopeAngle = 30.0f;
|
|
||||||
public float alignRate = 10.0f;
|
|
||||||
public float rayOffset = 0.1f;
|
|
||||||
|
|
||||||
public LayerMask groundMask = 1;
|
|
||||||
|
|
||||||
[Space(15f)]
|
|
||||||
public bool drawRays = true;
|
|
||||||
|
|
||||||
private readonly RaycastHit[] _hits = new RaycastHit[8];
|
|
||||||
|
|
||||||
private Character _character;
|
|
||||||
|
|
||||||
// Implement IColliderFilter.
|
|
||||||
// Ignore character's capsule collider.
|
|
||||||
|
|
||||||
public bool Filter(Collider otherCollider)
|
|
||||||
{
|
|
||||||
CharacterMovement characterMovement = _character.GetCharacterMovement();
|
|
||||||
if (otherCollider == characterMovement.collider)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Computes the average normal sampling a 3x3 area, each ray is a rayOffset distance of other.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
private Vector3 ComputeAverageNormal()
|
|
||||||
{
|
|
||||||
CharacterMovement characterMovement = _character.GetCharacterMovement();
|
|
||||||
|
|
||||||
Vector3 worldUp = Vector3.up;
|
|
||||||
Vector3 castOrigin = _character.GetPosition() + worldUp * (characterMovement.height * 0.5f);
|
|
||||||
|
|
||||||
Vector3 castDirection = -worldUp;
|
|
||||||
float castDistance = characterMovement.height;
|
|
||||||
LayerMask castLayerMask = groundMask;
|
|
||||||
|
|
||||||
Vector3 avgNormal = Vector3.zero;
|
|
||||||
|
|
||||||
float x = -rayOffset;
|
|
||||||
float z = -rayOffset;
|
|
||||||
|
|
||||||
int hitCount = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
z = -rayOffset;
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++)
|
|
||||||
{
|
|
||||||
bool hit = CollisionDetection.Raycast(castOrigin + new Vector3(x, 0.0f, z), castDirection,
|
|
||||||
castDistance, castLayerMask, QueryTriggerInteraction.Ignore, out RaycastHit hitResult, _hits, this) > 0;
|
|
||||||
|
|
||||||
if (hit)
|
|
||||||
{
|
|
||||||
float angle = Vector3.Angle(hitResult.normal, worldUp);
|
|
||||||
if (angle < maxSlopeAngle)
|
|
||||||
{
|
|
||||||
avgNormal += hitResult.normal;
|
|
||||||
|
|
||||||
if (drawRays)
|
|
||||||
Debug.DrawRay(hitResult.point, hitResult.normal, Color.yellow);
|
|
||||||
|
|
||||||
hitCount ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
z += rayOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
x += rayOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hitCount > 0)
|
|
||||||
avgNormal /= hitCount;
|
|
||||||
else
|
|
||||||
avgNormal = worldUp;
|
|
||||||
|
|
||||||
if (drawRays)
|
|
||||||
Debug.DrawRay(_character.GetPosition(), avgNormal * 2f, Color.green);
|
|
||||||
|
|
||||||
return avgNormal;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAfterSimulationUpdated(float deltaTime)
|
|
||||||
{
|
|
||||||
Vector3 avgNormal = _character.IsWalking() ? ComputeAverageNormal() : Vector3.up;
|
|
||||||
|
|
||||||
Quaternion characterRotation = _character.GetRotation();
|
|
||||||
Vector3 characterUp = characterRotation * Vector3.up;
|
|
||||||
|
|
||||||
Quaternion slopeRotation = Quaternion.FromToRotation(characterUp, avgNormal);
|
|
||||||
characterRotation = Quaternion.Slerp(characterRotation, slopeRotation * characterRotation, alignRate * deltaTime);
|
|
||||||
|
|
||||||
_character.SetRotation(characterRotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_character = GetComponent<Character>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_character.AfterSimulationUpdated += OnAfterSimulationUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDisable()
|
|
||||||
{
|
|
||||||
_character.AfterSimulationUpdated -= OnAfterSimulationUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ddceac5c369948b4b1f56559e4d41796
|
|
||||||
timeCreated: 1700621503
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3938dc9601b64b80aad092fdd3b438bf
|
|
||||||
timeCreated: 1700523966
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a053c6add13e16f4fb8b91a32c583756
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5baa8109e4051dd4980b7e59de338ef3
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b200f749d8db4954d8599e6772165940
|
|
||||||
NativeFormatImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
mainObjectFileID: 112000000
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Binary file not shown.
@@ -1,117 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 23407264829349547ae7a870aa3ebae8
|
|
||||||
TextureImporter:
|
|
||||||
internalIDToNameTable: []
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 13
|
|
||||||
mipmaps:
|
|
||||||
mipMapMode: 0
|
|
||||||
enableMipMap: 1
|
|
||||||
sRGBTexture: 1
|
|
||||||
linearTexture: 0
|
|
||||||
fadeOut: 0
|
|
||||||
borderMipMap: 0
|
|
||||||
mipMapsPreserveCoverage: 0
|
|
||||||
alphaTestReferenceValue: 0.5
|
|
||||||
mipMapFadeDistanceStart: 1
|
|
||||||
mipMapFadeDistanceEnd: 3
|
|
||||||
bumpmap:
|
|
||||||
convertToNormalMap: 0
|
|
||||||
externalNormalMap: 0
|
|
||||||
heightScale: 0.25
|
|
||||||
normalMapFilter: 0
|
|
||||||
flipGreenChannel: 0
|
|
||||||
isReadable: 0
|
|
||||||
streamingMipmaps: 0
|
|
||||||
streamingMipmapsPriority: 0
|
|
||||||
vTOnly: 0
|
|
||||||
ignoreMipmapLimit: 0
|
|
||||||
grayScaleToAlpha: 0
|
|
||||||
generateCubemap: 6
|
|
||||||
cubemapConvolution: 1
|
|
||||||
seamlessCubemap: 1
|
|
||||||
textureFormat: 1
|
|
||||||
maxTextureSize: 2048
|
|
||||||
textureSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
filterMode: 2
|
|
||||||
aniso: 0
|
|
||||||
mipBias: 0
|
|
||||||
wrapU: 1
|
|
||||||
wrapV: 1
|
|
||||||
wrapW: 1
|
|
||||||
nPOTScale: 1
|
|
||||||
lightmap: 0
|
|
||||||
compressionQuality: 50
|
|
||||||
spriteMode: 0
|
|
||||||
spriteExtrude: 1
|
|
||||||
spriteMeshType: 1
|
|
||||||
alignment: 0
|
|
||||||
spritePivot: {x: 0.5, y: 0.5}
|
|
||||||
spritePixelsToUnits: 100
|
|
||||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
|
||||||
spriteGenerateFallbackPhysicsShape: 1
|
|
||||||
alphaUsage: 1
|
|
||||||
alphaIsTransparency: 0
|
|
||||||
spriteTessellationDetail: -1
|
|
||||||
textureType: 0
|
|
||||||
textureShape: 2
|
|
||||||
singleChannelComponent: 0
|
|
||||||
flipbookRows: 1
|
|
||||||
flipbookColumns: 1
|
|
||||||
maxTextureSizeSet: 0
|
|
||||||
compressionQualitySet: 0
|
|
||||||
textureFormatSet: 0
|
|
||||||
ignorePngGamma: 0
|
|
||||||
applyGammaDecoding: 0
|
|
||||||
swizzle: 50462976
|
|
||||||
cookieLightType: 0
|
|
||||||
platformSettings:
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: DefaultTexturePlatform
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 100
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
- serializedVersion: 4
|
|
||||||
buildTarget: Standalone
|
|
||||||
maxTextureSize: 2048
|
|
||||||
resizeAlgorithm: 0
|
|
||||||
textureFormat: -1
|
|
||||||
textureCompression: 1
|
|
||||||
compressionQuality: 50
|
|
||||||
crunchedCompression: 0
|
|
||||||
allowsAlphaSplitting: 0
|
|
||||||
overridden: 0
|
|
||||||
ignorePlatformSupport: 0
|
|
||||||
androidETC2FallbackOverride: 0
|
|
||||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
|
||||||
spriteSheet:
|
|
||||||
serializedVersion: 2
|
|
||||||
sprites: []
|
|
||||||
outline: []
|
|
||||||
customData:
|
|
||||||
physicsShape: []
|
|
||||||
bones: []
|
|
||||||
spriteID:
|
|
||||||
internalID: 0
|
|
||||||
vertices: []
|
|
||||||
indices:
|
|
||||||
edges: []
|
|
||||||
weights: []
|
|
||||||
secondaryTextures: []
|
|
||||||
spriteCustomMetadata:
|
|
||||||
entries: []
|
|
||||||
nameFileIdTable: {}
|
|
||||||
mipmapLimitGroupName:
|
|
||||||
pSDRemoveMatte: 0
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f02f1530dd241694b817ab613b519138
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using ECM2.Examples.ThirdPerson;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.PlanetWalk
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example extends a Character (through inheritance) adjusting its gravity and orientation
|
|
||||||
/// to follow a planet curvature similar to the Mario Galaxy game.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class PlayerCharacter : ThirdPersonCharacter
|
|
||||||
{
|
|
||||||
[Space(15f)]
|
|
||||||
public Transform planetTransform;
|
|
||||||
|
|
||||||
// Current camera forward, perpendicular to target's up vector.
|
|
||||||
|
|
||||||
private Vector3 _cameraForward = Vector3.forward;
|
|
||||||
|
|
||||||
public override void AddControlYawInput(float value)
|
|
||||||
{
|
|
||||||
// Rotate our forward along follow target's up axis
|
|
||||||
|
|
||||||
Vector3 targetUp = followTarget.transform.up;
|
|
||||||
_cameraForward = Quaternion.Euler(targetUp * value) * _cameraForward;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateCameraRotation()
|
|
||||||
{
|
|
||||||
// Make sure camera forward vector is perpendicular to Character's current up vector
|
|
||||||
|
|
||||||
Vector3 targetUp = followTarget.transform.up;
|
|
||||||
Vector3.OrthoNormalize(ref targetUp, ref _cameraForward);
|
|
||||||
|
|
||||||
// Computes final Camera rotation from yaw and pitch
|
|
||||||
|
|
||||||
cameraTransform.rotation =
|
|
||||||
Quaternion.LookRotation(_cameraForward, targetUp) * Quaternion.Euler(_cameraPitch, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void UpdateRotation(float deltaTime)
|
|
||||||
{
|
|
||||||
// Call base method (i.e: rotate towards movement direction)
|
|
||||||
|
|
||||||
base.UpdateRotation(deltaTime);
|
|
||||||
|
|
||||||
// Adjust gravity direction (ie: a vector pointing from character position to planet's center)
|
|
||||||
|
|
||||||
Vector3 toPlanet = planetTransform.position - GetPosition();
|
|
||||||
SetGravityVector(toPlanet.normalized * GetGravityMagnitude());
|
|
||||||
|
|
||||||
// Adjust Character's rotation following the new world-up (defined by gravity direction)
|
|
||||||
|
|
||||||
Vector3 worldUp = GetGravityDirection() * -1.0f;
|
|
||||||
Quaternion newRotation = Quaternion.FromToRotation(GetUpVector(), worldUp) * GetRotation();
|
|
||||||
|
|
||||||
SetRotation(newRotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d8e22f557fff8be48a9230f99a4a6f52
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 148600c99f8ab8849975d72f538c9b3c
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: af237fa0d4164de3b8bbb1640d85f70b
|
|
||||||
timeCreated: 1700798056
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.SideScrolling
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example shows how to implement a typical side-scrolling movement with side to side rotation snap.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class SideScrollingInput : CharacterInput
|
|
||||||
{
|
|
||||||
protected override void Awake()
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.Awake();
|
|
||||||
|
|
||||||
// Disable Character rotation, well handle it here (snap move direction)
|
|
||||||
|
|
||||||
character.SetRotationMode(Character.RotationMode.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void HandleInput()
|
|
||||||
{
|
|
||||||
// Add horizontal movement (in world space)
|
|
||||||
|
|
||||||
Vector2 movementInput = GetMovementInput();
|
|
||||||
character.SetMovementDirection(Vector3.right * movementInput.x);
|
|
||||||
|
|
||||||
// Snap side to side rotation
|
|
||||||
|
|
||||||
if (movementInput.x != 0)
|
|
||||||
character.SetYaw(movementInput.x * 90.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8f138cba3d2dc7146817f32230b4f5b5
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9d6613720d4108f4fa955b37a378bbdc
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0a4fe6b8eae2cde41a0bbf010cfe55d2
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9a7cb1b2a4b6ebc4bbc670e46e857527
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,216 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace ECM2.Examples.Slide
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This example extends a Character (through inheritance) implementing a slide mechanic.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public class PlayerCharacter : Character
|
|
||||||
{
|
|
||||||
[Space(15.0f)]
|
|
||||||
public float slideImpulse = 20.0f;
|
|
||||||
public float slideDownAcceleration = 20.0f;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Our custom movement mode(s) id(s).
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
enum ECustomMovementMode
|
|
||||||
{
|
|
||||||
Sliding = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If sliding, return max walk speed as our speed limit.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public override float GetMaxSpeed()
|
|
||||||
{
|
|
||||||
return IsSliding() ? maxWalkSpeed : base.GetMaxSpeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If sliding, limit acceleration.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public override float GetMaxAcceleration()
|
|
||||||
{
|
|
||||||
return IsSliding() ? maxAcceleration * 0.1f : base.GetMaxAcceleration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Override IsWalking (aka: grounded movement mode) to add Sliding movement mode support,
|
|
||||||
/// otherwise crouch, jump will fail while sliding due its conditions checking if IsWalking.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public override bool IsWalking()
|
|
||||||
{
|
|
||||||
return IsSliding() || base.IsWalking();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Is the Character sliding?
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public bool IsSliding()
|
|
||||||
{
|
|
||||||
return movementMode == MovementMode.Custom && customMovementMode == (int)ECustomMovementMode.Sliding;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines if the character can slide in its current state.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual bool CanSlide()
|
|
||||||
{
|
|
||||||
// Slide is tied to crouch, if not crouching cant slide!
|
|
||||||
|
|
||||||
if (!IsGrounded())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check allowed slide speed threshold
|
|
||||||
|
|
||||||
float sqrSpeed = velocity.sqrMagnitude;
|
|
||||||
float slideSpeedThreshold = maxWalkSpeedCrouched * maxWalkSpeedCrouched;
|
|
||||||
|
|
||||||
return sqrSpeed >= slideSpeedThreshold * 1.02f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculate sliding direction vector.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual Vector3 CalcSlideDirection()
|
|
||||||
{
|
|
||||||
Vector3 slideDirection = GetMovementDirection();
|
|
||||||
if (slideDirection.isZero())
|
|
||||||
slideDirection = GetVelocity();
|
|
||||||
else if (slideDirection.isZero())
|
|
||||||
slideDirection = GetForwardVector();
|
|
||||||
|
|
||||||
slideDirection = ConstrainInputVector(slideDirection);
|
|
||||||
|
|
||||||
return slideDirection.normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Attempts to perform a requested slide or
|
|
||||||
/// stop it if requested or cant continue sliding.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void CheckSlideInput()
|
|
||||||
{
|
|
||||||
bool isSliding = IsSliding();
|
|
||||||
bool wantsToSlide = crouchInputPressed;
|
|
||||||
|
|
||||||
if (!isSliding && wantsToSlide && CanSlide())
|
|
||||||
{
|
|
||||||
SetMovementMode(MovementMode.Custom, (int)ECustomMovementMode.Sliding);
|
|
||||||
}
|
|
||||||
else if (isSliding && (!wantsToSlide || !CanSlide()))
|
|
||||||
{
|
|
||||||
SetMovementMode(MovementMode.Walking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handle Sliding enter / exit.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected override void OnMovementModeChanged(MovementMode prevMovementMode, int prevCustomMode)
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.OnMovementModeChanged(prevMovementMode, prevCustomMode);
|
|
||||||
|
|
||||||
// Enter sliding movement mode...
|
|
||||||
|
|
||||||
if (IsSliding())
|
|
||||||
{
|
|
||||||
// Apply initial slide impulse
|
|
||||||
|
|
||||||
Vector3 slideDirection = CalcSlideDirection();
|
|
||||||
characterMovement.velocity += slideDirection * slideImpulse;
|
|
||||||
|
|
||||||
// Disable Character rotation
|
|
||||||
|
|
||||||
SetRotationMode(RotationMode.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exit sliding movement mode...
|
|
||||||
|
|
||||||
bool wasSliding = prevMovementMode == MovementMode.Custom &&
|
|
||||||
prevCustomMode == (int)ECustomMovementMode.Sliding;
|
|
||||||
|
|
||||||
if (wasSliding)
|
|
||||||
{
|
|
||||||
// Re-enable Character rotation
|
|
||||||
|
|
||||||
SetRotationMode(RotationMode.OrientRotationToMovement);
|
|
||||||
|
|
||||||
// If falling, make sure its velocity do not exceed maxWalkSpeed
|
|
||||||
|
|
||||||
if (IsFalling())
|
|
||||||
{
|
|
||||||
Vector3 worldUp = -GetGravityDirection();
|
|
||||||
Vector3 verticalVelocity = Vector3.Project(velocity, worldUp);
|
|
||||||
Vector3 lateralVelocity = Vector3.ClampMagnitude(velocity - verticalVelocity, maxWalkSpeed);
|
|
||||||
|
|
||||||
characterMovement.velocity = lateralVelocity + verticalVelocity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBeforeSimulationUpdate(float deltaTime)
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.OnBeforeSimulationUpdate(deltaTime);
|
|
||||||
|
|
||||||
// Attempts to do a requested slide
|
|
||||||
|
|
||||||
CheckSlideInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update Character's velocity while SLIDING on walkable surfaces.
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
protected virtual void SlidingMovementMode(float deltaTime)
|
|
||||||
{
|
|
||||||
// Limit input to lateral movement only (strafing)
|
|
||||||
|
|
||||||
Vector3 desiredVelocity = Vector3.Project(GetDesiredVelocity(), GetRightVector());
|
|
||||||
|
|
||||||
// Calculate new velocity
|
|
||||||
|
|
||||||
characterMovement.velocity =
|
|
||||||
CalcVelocity(characterMovement.velocity, desiredVelocity, groundFriction * 0.2f, false, deltaTime);
|
|
||||||
|
|
||||||
// Apply slide down acceleration
|
|
||||||
|
|
||||||
Vector3 slideDownDirection =
|
|
||||||
Vector3.ProjectOnPlane(GetGravityDirection(), characterMovement.groundNormal).normalized;
|
|
||||||
|
|
||||||
characterMovement.velocity += slideDownAcceleration * deltaTime * slideDownDirection;
|
|
||||||
|
|
||||||
// Apply downwards force
|
|
||||||
|
|
||||||
if (applyStandingDownwardForce)
|
|
||||||
ApplyDownwardsForce();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void CustomMovementMode(float deltaTime)
|
|
||||||
{
|
|
||||||
// Call base method implementation
|
|
||||||
|
|
||||||
base.CustomMovementMode(deltaTime);
|
|
||||||
|
|
||||||
// Sliding custom movement mode
|
|
||||||
|
|
||||||
if (customMovementMode == (int)ECustomMovementMode.Sliding)
|
|
||||||
SlidingMovementMode(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user