Upload project

This commit is contained in:
Lauchstange committed 2025-01-30 17:20:27 +01:00
1 parent 6bbeab16d1
commit bf545f3baf
371 files changed
+91095

No files matched your search

@@ -0,0 +1,229 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Authoring;
using Unity.Physics.Extensions;
using Unity.Physics.Systems;
using Unity.Transforms;
using Unity.CharacterController;
using UnityEngine;
public struct FirstPersonCharacterUpdateContext
{
// Here, you may add additional global data for your character updates, such as ComponentLookups, Singletons, NativeCollections, etc...
// The data you add here will be accessible in your character updates and all of your character "callbacks".
public void OnSystemCreate(ref SystemState state)
{
// Get lookups
}
public void OnSystemUpdate(ref SystemState state)
{
// Update lookups
}
}
public readonly partial struct FirstPersonCharacterAspect : IAspect, IKinematicCharacterProcessor<FirstPersonCharacterUpdateContext>
{
public readonly KinematicCharacterAspect CharacterAspect;
public readonly RefRW<FirstPersonCharacterComponent> CharacterComponent;
public readonly RefRW<FirstPersonCharacterControl> CharacterControl;
public void PhysicsUpdate(ref FirstPersonCharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext)
{
ref FirstPersonCharacterComponent characterComponent = ref CharacterComponent.ValueRW;
ref KinematicCharacterBody characterBody = ref CharacterAspect.CharacterBody.ValueRW;
ref float3 characterPosition = ref CharacterAspect.LocalTransform.ValueRW.Position;
// First phase of default character update
CharacterAspect.Update_Initialize(in this, ref context, ref baseContext, ref characterBody, baseContext.Time.DeltaTime);
CharacterAspect.Update_ParentMovement(in this, ref context, ref baseContext, ref characterBody, ref characterPosition, characterBody.WasGroundedBeforeCharacterUpdate);
CharacterAspect.Update_Grounding(in this, ref context, ref baseContext, ref characterBody, ref characterPosition);
// Update desired character velocity after grounding was detected, but before doing additional processing that depends on velocity
HandleVelocityControl(ref context, ref baseContext);
// Second phase of default character update
CharacterAspect.Update_PreventGroundingFromFutureSlopeChange(in this, ref context, ref baseContext, ref characterBody, in characterComponent.StepAndSlopeHandling);
CharacterAspect.Update_GroundPushing(in this, ref context, ref baseContext, characterComponent.Gravity);
CharacterAspect.Update_MovementAndDecollisions(in this, ref context, ref baseContext, ref characterBody, ref characterPosition);
CharacterAspect.Update_MovingPlatformDetection(ref baseContext, ref characterBody);
CharacterAspect.Update_ParentMomentum(ref baseContext, ref characterBody);
CharacterAspect.Update_ProcessStatefulCharacterHits();
}
private void HandleVelocityControl(ref FirstPersonCharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext)
{
float deltaTime = baseContext.Time.DeltaTime;
ref KinematicCharacterBody characterBody = ref CharacterAspect.CharacterBody.ValueRW;
ref FirstPersonCharacterComponent characterComponent = ref CharacterComponent.ValueRW;
ref FirstPersonCharacterControl characterControl = ref CharacterControl.ValueRW;
// Rotate move input and velocity to take into account parent rotation
if(characterBody.ParentEntity != Entity.Null)
{
characterControl.MoveVector = math.rotate(characterBody.RotationFromParent, characterControl.MoveVector);
characterBody.RelativeVelocity = math.rotate(characterBody.RotationFromParent, characterBody.RelativeVelocity);
}
if (characterBody.IsGrounded)
{
// Move on ground
float3 targetVelocity = characterControl.MoveVector * characterComponent.GroundMaxSpeed;
CharacterControlUtilities.StandardGroundMove_Interpolated(ref characterBody.RelativeVelocity, targetVelocity, characterComponent.GroundedMovementSharpness, deltaTime, characterBody.GroundingUp, characterBody.GroundHit.Normal);
// Jump
if (characterControl.Jump)
{
CharacterControlUtilities.StandardJump(ref characterBody, characterBody.GroundingUp * characterComponent.JumpSpeed, true, characterBody.GroundingUp);
}
}
else
{
// Move in air
float3 airAcceleration = characterControl.MoveVector * characterComponent.AirAcceleration;
if (math.lengthsq(airAcceleration) > 0f)
{
float3 tmpVelocity = characterBody.RelativeVelocity;
CharacterControlUtilities.StandardAirMove(ref characterBody.RelativeVelocity, airAcceleration, characterComponent.AirMaxSpeed, characterBody.GroundingUp, deltaTime, false);
// Cancel air acceleration from input if we would hit a non-grounded surface (prevents air-climbing slopes at high air accelerations)
if (characterComponent.PreventAirAccelerationAgainstUngroundedHits && CharacterAspect.MovementWouldHitNonGroundedObstruction(in this, ref context, ref baseContext, characterBody.RelativeVelocity * deltaTime, out ColliderCastHit hit))
{
characterBody.RelativeVelocity = tmpVelocity;
}
}
// Gravity
CharacterControlUtilities.AccelerateVelocity(ref characterBody.RelativeVelocity, characterComponent.Gravity, deltaTime);
// Drag
CharacterControlUtilities.ApplyDragToVelocity(ref characterBody.RelativeVelocity, deltaTime, characterComponent.AirDrag);
}
}
public void VariableUpdate(ref FirstPersonCharacterUpdateContext context, ref KinematicCharacterUpdateContext baseContext)
{
ref KinematicCharacterBody characterBody = ref CharacterAspect.CharacterBody.ValueRW;
ref FirstPersonCharacterComponent characterComponent = ref CharacterComponent.ValueRW;
ref FirstPersonCharacterControl characterControl = ref CharacterControl.ValueRW;
ref quaternion characterRotation = ref CharacterAspect.LocalTransform.ValueRW.Rotation;
// Add rotation from parent body to the character rotation
// (this is for allowing a rotating moving platform to rotate your character as well, and handle interpolation properly)
KinematicCharacterUtilities.AddVariableRateRotationFromFixedRateRotation(ref characterRotation, characterBody.RotationFromParent, baseContext.Time.DeltaTime, characterBody.LastPhysicsUpdateDeltaTime);
// Compute character & view rotations from rotation input
FirstPersonCharacterUtilities.ComputeFinalRotationsFromRotationDelta(
ref characterRotation,
ref characterComponent.ViewPitchDegrees,
characterControl.LookDegreesDelta,
0f,
characterComponent.MinViewAngle,
characterComponent.MaxViewAngle,
out float canceledPitchDegrees,
out characterComponent.ViewLocalRotation);
}
#region Character Processor Callbacks
public void UpdateGroundingUp(
ref FirstPersonCharacterUpdateContext context,
ref KinematicCharacterUpdateContext baseContext)
{
ref KinematicCharacterBody characterBody = ref CharacterAspect.CharacterBody.ValueRW;
CharacterAspect.Default_UpdateGroundingUp(ref characterBody);
}
public bool CanCollideWithHit(
ref FirstPersonCharacterUpdateContext context,
ref KinematicCharacterUpdateContext baseContext,
in BasicHit hit)
{
return PhysicsUtilities.IsCollidable(hit.Material);
}
public bool IsGroundedOnHit(
ref FirstPersonCharacterUpdateContext context,
ref KinematicCharacterUpdateContext baseContext,
in BasicHit hit,
int groundingEvaluationType)
{
FirstPersonCharacterComponent characterComponent = CharacterComponent.ValueRO;
return CharacterAspect.Default_IsGroundedOnHit(
in this,
ref context,
ref baseContext,
in hit,
in characterComponent.StepAndSlopeHandling,
groundingEvaluationType);
}
public void OnMovementHit(
ref FirstPersonCharacterUpdateContext context,
ref KinematicCharacterUpdateContext baseContext,
ref KinematicCharacterHit hit,
ref float3 remainingMovementDirection,
ref float remainingMovementLength,
float3 originalVelocityDirection,
float hitDistance)
{
ref KinematicCharacterBody characterBody = ref CharacterAspect.CharacterBody.ValueRW;
ref float3 characterPosition = ref CharacterAspect.LocalTransform.ValueRW.Position;
FirstPersonCharacterComponent characterComponent = CharacterComponent.ValueRO;
CharacterAspect.Default_OnMovementHit(
in this,
ref context,
ref baseContext,
ref characterBody,
ref characterPosition,
ref hit,
ref remainingMovementDirection,
ref remainingMovementLength,
originalVelocityDirection,
hitDistance,
characterComponent.StepAndSlopeHandling.StepHandling,
characterComponent.StepAndSlopeHandling.MaxStepHeight,
characterComponent.StepAndSlopeHandling.CharacterWidthForStepGroundingCheck);
}
public void OverrideDynamicHitMasses(
ref FirstPersonCharacterUpdateContext context,
ref KinematicCharacterUpdateContext baseContext,
ref PhysicsMass characterMass,
ref PhysicsMass otherMass,
BasicHit hit)
{
// Custom mass overrides
}
public void ProjectVelocityOnHits(
ref FirstPersonCharacterUpdateContext context,
ref KinematicCharacterUpdateContext baseContext,
ref float3 velocity,
ref bool characterIsGrounded,
ref BasicHit characterGroundHit,
in DynamicBuffer<KinematicVelocityProjectionHit> velocityProjectionHits,
float3 originalVelocityDirection)
{
FirstPersonCharacterComponent characterComponent = CharacterComponent.ValueRO;
CharacterAspect.Default_ProjectVelocityOnHits(
ref velocity,
ref characterIsGrounded,
ref characterGroundHit,
in velocityProjectionHits,
originalVelocityDirection,
characterComponent.StepAndSlopeHandling.ConstrainVelocityToGroundPlane);
}
#endregion
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5e8284f926e5e7448f516cf2f1b9519
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,57 @@
using Unity.Entities;
using Unity.Mathematics;
using Unity.Physics.Authoring;
using UnityEngine;
using Unity.CharacterController;
using Unity.Physics;
using System.Collections.Generic;
using UnityEngine.Serialization;
[DisallowMultipleComponent]
public class FirstPersonCharacterAuthoring : MonoBehaviour
{
public GameObject ViewEntity;
public AuthoringKinematicCharacterProperties CharacterProperties = AuthoringKinematicCharacterProperties.GetDefault();
public float GroundMaxSpeed = 10f;
public float GroundedMovementSharpness = 15f;
public float AirAcceleration = 50f;
public float AirMaxSpeed = 10f;
public float AirDrag = 0f;
public float JumpSpeed = 10f;
public float3 Gravity = math.up() * -30f;
public bool PreventAirAccelerationAgainstUngroundedHits = true;
public BasicStepAndSlopeHandlingParameters StepAndSlopeHandling = BasicStepAndSlopeHandlingParameters.GetDefault();
public float MinViewAngle = -90f;
public float MaxViewAngle = 90f;
public class Baker : Baker<FirstPersonCharacterAuthoring>
{
public override void Bake(FirstPersonCharacterAuthoring authoring)
{
KinematicCharacterUtilities.BakeCharacter(this, authoring.gameObject, authoring.CharacterProperties);
Entity entity = GetEntity(TransformUsageFlags.Dynamic | TransformUsageFlags.WorldSpace);
AddComponent(entity, new FirstPersonCharacterComponent
{
GroundMaxSpeed = authoring.GroundMaxSpeed,
GroundedMovementSharpness = authoring.GroundedMovementSharpness,
AirAcceleration = authoring.AirAcceleration,
AirMaxSpeed = authoring.AirMaxSpeed,
AirDrag = authoring.AirDrag,
JumpSpeed = authoring.JumpSpeed,
Gravity = authoring.Gravity,
PreventAirAccelerationAgainstUngroundedHits = authoring.PreventAirAccelerationAgainstUngroundedHits,
StepAndSlopeHandling = authoring.StepAndSlopeHandling,
MinViewAngle = authoring.MinViewAngle,
MaxViewAngle = authoring.MaxViewAngle,
ViewEntity = GetEntity(authoring.ViewEntity, TransformUsageFlags.Dynamic),
ViewPitchDegrees = 0f,
ViewLocalRotation = quaternion.identity,
});
AddComponent(entity, new FirstPersonCharacterControl());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03c9592a80483fd478e45d176ac83132
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,41 @@
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using Unity.CharacterController;
[Serializable]
public struct FirstPersonCharacterComponent : IComponentData
{
public float GroundMaxSpeed;
public float GroundedMovementSharpness;
public float AirAcceleration;
public float AirMaxSpeed;
public float AirDrag;
public float JumpSpeed;
public float3 Gravity;
public bool PreventAirAccelerationAgainstUngroundedHits;
public BasicStepAndSlopeHandlingParameters StepAndSlopeHandling;
public float MinViewAngle;
public float MaxViewAngle;
public Entity ViewEntity;
public float ViewPitchDegrees;
public quaternion ViewLocalRotation;
}
[Serializable]
public struct FirstPersonCharacterControl : IComponentData
{
public float3 MoveVector;
public float2 LookDegreesDelta;
public bool Jump;
}
[Serializable]
public struct FirstPersonCharacterView : IComponentData
{
public Entity CharacterEntity;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 639e80f96b7d5f94bbb37c78f27edecd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,160 @@
using Unity.Burst;
using Unity.Entities;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Transforms;
using Unity.CharacterController;
using Unity.Burst.Intrinsics;
[UpdateInGroup(typeof(KinematicCharacterPhysicsUpdateGroup))]
[BurstCompile]
public partial struct FirstPersonCharacterPhysicsUpdateSystem : ISystem
{
private EntityQuery _characterQuery;
private FirstPersonCharacterUpdateContext _context;
private KinematicCharacterUpdateContext _baseContext;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
_characterQuery = KinematicCharacterUtilities.GetBaseCharacterQueryBuilder()
.WithAll<
FirstPersonCharacterComponent,
FirstPersonCharacterControl>()
.Build(ref state);
_context = new FirstPersonCharacterUpdateContext();
_context.OnSystemCreate(ref state);
_baseContext = new KinematicCharacterUpdateContext();
_baseContext.OnSystemCreate(ref state);
state.RequireForUpdate(_characterQuery);
state.RequireForUpdate<PhysicsWorldSingleton>();
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
_context.OnSystemUpdate(ref state);
_baseContext.OnSystemUpdate(ref state, SystemAPI.Time, SystemAPI.GetSingleton<PhysicsWorldSingleton>());
FirstPersonCharacterPhysicsUpdateJob job = new FirstPersonCharacterPhysicsUpdateJob
{
Context = _context,
BaseContext = _baseContext,
};
job.ScheduleParallel();
}
[BurstCompile]
[WithAll(typeof(Simulate))]
public partial struct FirstPersonCharacterPhysicsUpdateJob : IJobEntity, IJobEntityChunkBeginEnd
{
public FirstPersonCharacterUpdateContext Context;
public KinematicCharacterUpdateContext BaseContext;
void Execute(FirstPersonCharacterAspect characterAspect)
{
characterAspect.PhysicsUpdate(ref Context, ref BaseContext);
}
public bool OnChunkBegin(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
BaseContext.EnsureCreationOfTmpCollections();
return true;
}
public void OnChunkEnd(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask, bool chunkWasExecuted)
{
}
}
}
[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(FixedStepSimulationSystemGroup))]
[UpdateAfter(typeof(FirstPersonPlayerVariableStepControlSystem))]
[UpdateBefore(typeof(TransformSystemGroup))]
[BurstCompile]
public partial struct FirstPersonCharacterVariableUpdateSystem : ISystem
{
private EntityQuery _characterQuery;
private FirstPersonCharacterUpdateContext _context;
private KinematicCharacterUpdateContext _baseContext;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
_characterQuery = KinematicCharacterUtilities.GetBaseCharacterQueryBuilder()
.WithAll<
FirstPersonCharacterComponent,
FirstPersonCharacterControl>()
.Build(ref state);
_context = new FirstPersonCharacterUpdateContext();
_context.OnSystemCreate(ref state);
_baseContext = new KinematicCharacterUpdateContext();
_baseContext.OnSystemCreate(ref state);
state.RequireForUpdate(_characterQuery);
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
_context.OnSystemUpdate(ref state);
_baseContext.OnSystemUpdate(ref state, SystemAPI.Time, SystemAPI.GetSingleton<PhysicsWorldSingleton>());
FirstPersonCharacterVariableUpdateJob variableUpdateJob = new FirstPersonCharacterVariableUpdateJob
{
Context = _context,
BaseContext = _baseContext,
};
variableUpdateJob.ScheduleParallel();
FirstPersonCharacterViewJob viewJob = new FirstPersonCharacterViewJob
{
FirstPersonCharacterLookup = SystemAPI.GetComponentLookup<FirstPersonCharacterComponent>(true),
};
viewJob.ScheduleParallel();
}
[BurstCompile]
[WithAll(typeof(Simulate))]
public partial struct FirstPersonCharacterVariableUpdateJob : IJobEntity, IJobEntityChunkBeginEnd
{
public FirstPersonCharacterUpdateContext Context;
public KinematicCharacterUpdateContext BaseContext;
void Execute(FirstPersonCharacterAspect characterAspect)
{
characterAspect.VariableUpdate(ref Context, ref BaseContext);
}
public bool OnChunkBegin(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
BaseContext.EnsureCreationOfTmpCollections();
return true;
}
public void OnChunkEnd(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask, bool chunkWasExecuted)
{ }
}
[BurstCompile]
[WithAll(typeof(Simulate))]
public partial struct FirstPersonCharacterViewJob : IJobEntity
{
[ReadOnly]
public ComponentLookup<FirstPersonCharacterComponent> FirstPersonCharacterLookup;
void Execute(ref LocalTransform localTransform, in FirstPersonCharacterView characterView)
{
if (FirstPersonCharacterLookup.TryGetComponent(characterView.CharacterEntity, out FirstPersonCharacterComponent character))
{
localTransform.Rotation = character.ViewLocalRotation;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8255af6f295149f41bc8baf529b5b711
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,135 @@
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.CharacterController;
public static class FirstPersonCharacterUtilities
{
public static quaternion GetCurrentWorldViewRotation(quaternion characterRotation, quaternion localCharacterViewRotation)
{
return math.mul(characterRotation, localCharacterViewRotation);
}
public static void GetCurrentWorldViewDirectionAndRotation(
quaternion characterRotation,
quaternion localCharacterViewRotation,
out float3 worldCharacterViewDirection,
out quaternion worldCharacterViewRotation)
{
worldCharacterViewRotation = GetCurrentWorldViewRotation(characterRotation, localCharacterViewRotation);
worldCharacterViewDirection = math.mul(worldCharacterViewRotation, math.forward());
}
public static void ComputeFinalRotationsFromTargetLookDirection(
ref quaternion characterRotation,
ref quaternion localCharacterViewRotation,
ref float3 targetLookDirection,
ref float viewPitchDegrees,
float viewRollDegrees,
float minViewPitchDegrees,
float maxViewPitchDegrees,
float3 characterUp)
{
// rotate character root to point at look direction on character up plane
float3 newCharacterForward = math.normalizesafe(MathUtilities.ProjectOnPlane(targetLookDirection, characterUp));
characterRotation = quaternion.LookRotationSafe(newCharacterForward, characterUp);
// calculate view pitch angles to look at target direction
viewPitchDegrees = math.degrees(MathUtilities.AngleRadians(newCharacterForward, targetLookDirection));
if (math.dot(characterUp, targetLookDirection) < 0f)
{
viewPitchDegrees *= -1f;
}
viewPitchDegrees = math.clamp(viewPitchDegrees, minViewPitchDegrees, maxViewPitchDegrees);
localCharacterViewRotation = CalculateLocalViewRotation(viewPitchDegrees, viewRollDegrees);
}
public static void ComputeFinalRotationsFromRotationDelta(
ref float viewPitchDegrees,
ref float characterRotationYDegrees,
float3 characterTransformUp,
float2 yawPitchDeltaDegrees,
float viewRollDegrees,
float minPitchDegrees,
float maxPitchDegrees,
out quaternion characterRotation,
out float canceledPitchDegrees,
out quaternion viewLocalRotation)
{
// Yaw
characterRotationYDegrees += yawPitchDeltaDegrees.x;
ComputeRotationFromYAngleAndUp(characterRotationYDegrees, characterTransformUp, out characterRotation);
// Pitch
viewPitchDegrees += yawPitchDeltaDegrees.y;
float viewPitchAngleDegreesBeforeClamp = viewPitchDegrees;
viewPitchDegrees = math.clamp(viewPitchDegrees, minPitchDegrees, maxPitchDegrees);
canceledPitchDegrees = yawPitchDeltaDegrees.y - (viewPitchAngleDegreesBeforeClamp - viewPitchDegrees);
viewLocalRotation = CalculateLocalViewRotation(viewPitchDegrees, viewRollDegrees);
}
public static void ComputeRotationFromYAngleAndUp(
float characterRotationYDegrees,
float3 characterTransformUp,
out quaternion characterRotation)
{
characterRotation = math.mul(MathUtilities.CreateRotationWithUpPriority(characterTransformUp, math.forward()), quaternion.Euler(0f, math.radians(characterRotationYDegrees), 0f));
}
public static void ComputeFinalRotationsFromRotationDelta(
ref quaternion characterRotation,
ref float viewPitchDegrees,
float2 yawPitchDeltaDegrees,
float viewRollDegrees,
float minPitchDegrees,
float maxPitchDegrees,
out float canceledPitchDegrees,
out quaternion viewLocalRotation)
{
// Yaw
quaternion yawRotation = quaternion.Euler(math.up() * math.radians(yawPitchDeltaDegrees.x));
characterRotation = math.mul(characterRotation, yawRotation);
// Pitch
viewPitchDegrees += yawPitchDeltaDegrees.y;
float viewPitchAngleDegreesBeforeClamp = viewPitchDegrees;
viewPitchDegrees = math.clamp(viewPitchDegrees, minPitchDegrees, maxPitchDegrees);
canceledPitchDegrees = yawPitchDeltaDegrees.y - (viewPitchAngleDegreesBeforeClamp - viewPitchDegrees);
viewLocalRotation = CalculateLocalViewRotation(viewPitchDegrees, viewRollDegrees);
}
public static quaternion CalculateLocalViewRotation(float viewPitchDegrees, float viewRollDegrees)
{
// Pitch
quaternion viewLocalRotation = quaternion.AxisAngle(-math.right(), math.radians(viewPitchDegrees));
// Roll
viewLocalRotation = math.mul(viewLocalRotation, quaternion.AxisAngle(math.forward(), math.radians(viewRollDegrees)));
return viewLocalRotation;
}
public static float3 ComputeTargetLookDirectionFromRotationAngles(
ref float viewPitchDegrees,
float minViewPitchDegrees,
float maxViewPitchDegrees,
float2 pitchYawDegrees,
quaternion characterRotation)
{
// Yaw
quaternion yawRotation = quaternion.Euler(math.up() * math.radians(pitchYawDegrees.x));
quaternion targetRotation = math.mul(characterRotation, yawRotation);
// Pitch
float tmpViewPitchAngleDegrees = viewPitchDegrees + pitchYawDegrees.y;
tmpViewPitchAngleDegrees = math.clamp(tmpViewPitchAngleDegrees, minViewPitchDegrees, maxViewPitchDegrees);
quaternion pitchRotation = quaternion.Euler(-math.right() * math.radians(tmpViewPitchAngleDegrees));
targetRotation = math.mul(targetRotation, pitchRotation);
return math.mul(targetRotation, math.forward());
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 446b6f888df7be748b79fecd775dff83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,26 @@
using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;
[DisallowMultipleComponent]
public class FirstPersonCharacterViewAuthoring : MonoBehaviour
{
public GameObject Character;
public class Baker : Baker<FirstPersonCharacterViewAuthoring>
{
public override void Bake(FirstPersonCharacterViewAuthoring authoring)
{
if (authoring.transform.parent != authoring.Character.transform)
{
UnityEngine.Debug.LogError("ERROR: the Character View must be a direct 1st-level child of the character authoring GameObject. Conversion will be aborted");
return;
}
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new FirstPersonCharacterView { CharacterEntity = GetEntity(authoring.Character, TransformUsageFlags.Dynamic) });
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f3ddd2cb094880b40a1612adcf67e9a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,18 @@
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
[Serializable]
public struct FirstPersonPlayer : IComponentData
{
public Entity ControlledCharacter;
}
[Serializable]
public struct FirstPersonPlayerInputs : IComponentData
{
public float2 MoveInput;
public float2 LookInput;
public FixedInputEvent JumpPressed;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b475ce53dfa6de64ea0a2e1beac9c141
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,21 @@
using UnityEngine;
using Unity.Entities;
[DisallowMultipleComponent]
public class FirstPersonPlayerAuthoring : MonoBehaviour
{
public GameObject ControlledCharacter;
public class Baker : Baker<FirstPersonPlayerAuthoring>
{
public override void Bake(FirstPersonPlayerAuthoring authoring)
{
Entity entity = GetEntity(TransformUsageFlags.None);
AddComponent(entity, new FirstPersonPlayer
{
ControlledCharacter = GetEntity(authoring.ControlledCharacter, TransformUsageFlags.Dynamic),
});
AddComponent<FirstPersonPlayerInputs>(entity);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 98df7776338bbf9418e4d50363a02333
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,113 @@
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
using Unity.CharacterController;
[UpdateInGroup(typeof(InitializationSystemGroup))]
public partial class FirstPersonPlayerInputsSystem : SystemBase
{
protected override void OnCreate()
{
RequireForUpdate<FixedTickSystem.Singleton>();
RequireForUpdate(SystemAPI.QueryBuilder().WithAll<FirstPersonPlayer, FirstPersonPlayerInputs>().Build());
}
protected override void OnUpdate()
{
uint tick = SystemAPI.GetSingleton<FixedTickSystem.Singleton>().Tick;
foreach (var (playerInputs, player) in SystemAPI.Query<RefRW<FirstPersonPlayerInputs>, FirstPersonPlayer>())
{
playerInputs.ValueRW.MoveInput = new float2
{
x = (Input.GetKey(KeyCode.D) ? 1f : 0f) + (Input.GetKey(KeyCode.A) ? -1f : 0f),
y = (Input.GetKey(KeyCode.W) ? 1f : 0f) + (Input.GetKey(KeyCode.S) ? -1f : 0f),
};
playerInputs.ValueRW.LookInput = new float2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
if (Input.GetKeyDown(KeyCode.Space))
{
playerInputs.ValueRW.JumpPressed.Set(tick);
}
}
}
}
/// <summary>
/// Apply inputs that need to be read at a variable rate
/// </summary>
[UpdateInGroup(typeof(SimulationSystemGroup))]
[UpdateAfter(typeof(FixedStepSimulationSystemGroup))]
[BurstCompile]
public partial struct FirstPersonPlayerVariableStepControlSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate(SystemAPI.QueryBuilder().WithAll<FirstPersonPlayer, FirstPersonPlayerInputs>().Build());
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
foreach (var (playerInputs, player) in SystemAPI.Query<FirstPersonPlayerInputs, FirstPersonPlayer>().WithAll<Simulate>())
{
if (SystemAPI.HasComponent<FirstPersonCharacterControl>(player.ControlledCharacter))
{
FirstPersonCharacterControl characterControl = SystemAPI.GetComponent<FirstPersonCharacterControl>(player.ControlledCharacter);
characterControl.LookDegreesDelta = playerInputs.LookInput;
SystemAPI.SetComponent(player.ControlledCharacter, characterControl);
}
}
}
}
/// <summary>
/// Apply inputs that need to be read at a fixed rate.
/// It is necessary to handle this as part of the fixed step group, in case your framerate is lower than the fixed step rate.
/// </summary>
[UpdateInGroup(typeof(FixedStepSimulationSystemGroup), OrderFirst = true)]
[BurstCompile]
public partial struct FirstPersonPlayerFixedStepControlSystem : ISystem
{
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<FixedTickSystem.Singleton>();
state.RequireForUpdate(SystemAPI.QueryBuilder().WithAll<FirstPersonPlayer, FirstPersonPlayerInputs>().Build());
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
uint tick = SystemAPI.GetSingleton<FixedTickSystem.Singleton>().Tick;
foreach (var (playerInputs, player) in SystemAPI.Query<FirstPersonPlayerInputs, FirstPersonPlayer>().WithAll<Simulate>())
{
if (SystemAPI.HasComponent<FirstPersonCharacterControl>(player.ControlledCharacter))
{
FirstPersonCharacterControl characterControl = SystemAPI.GetComponent<FirstPersonCharacterControl>(player.ControlledCharacter);
quaternion characterRotation = SystemAPI.GetComponent<LocalTransform>(player.ControlledCharacter).Rotation;
// Move
float3 characterForward = MathUtilities.GetForwardFromRotation(characterRotation);
float3 characterRight = MathUtilities.GetRightFromRotation(characterRotation);
characterControl.MoveVector = (playerInputs.MoveInput.y * characterForward) + (playerInputs.MoveInput.x * characterRight);
characterControl.MoveVector = MathUtilities.ClampToMaxLength(characterControl.MoveVector, 1f);
// Jump
characterControl.Jump = playerInputs.JumpPressed.IsSet(tick);
SystemAPI.SetComponent(player.ControlledCharacter, characterControl);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 068c7fe0e7567404cb30b0d8715b4560
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: