Upload project
This commit is contained in:
1 parent
6bbeab16d1
commit
bf545f3baf
371 files changed
+91095
No files matched your search
+10
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
|
||||
[Serializable]
|
||||
public struct CameraTarget : IComponentData
|
||||
{
|
||||
public Entity TargetEntity;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74ff9a59933a5494bbc1bb465a5f2180
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Unity.Entities;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public class CameraTargetAuthoring : MonoBehaviour
|
||||
{
|
||||
public GameObject Target;
|
||||
|
||||
public class Baker : Baker<CameraTargetAuthoring>
|
||||
{
|
||||
public override void Bake(CameraTargetAuthoring authoring)
|
||||
{
|
||||
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
|
||||
AddComponent(entity, new CameraTarget
|
||||
{
|
||||
TargetEntity = GetEntity(authoring.Target, TransformUsageFlags.Dynamic),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3a88336df575c34e80048c54a815367
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
[Serializable]
|
||||
public struct OrbitCamera : IComponentData
|
||||
{
|
||||
public float RotationSpeed;
|
||||
public float MaxVAngle;
|
||||
public float MinVAngle;
|
||||
public bool RotateWithCharacterParent;
|
||||
|
||||
public float MinDistance;
|
||||
public float MaxDistance;
|
||||
public float DistanceMovementSpeed;
|
||||
public float DistanceMovementSharpness;
|
||||
|
||||
public float ObstructionRadius;
|
||||
public float ObstructionInnerSmoothingSharpness;
|
||||
public float ObstructionOuterSmoothingSharpness;
|
||||
public bool PreventFixedUpdateJitter;
|
||||
|
||||
public float TargetDistance;
|
||||
public float SmoothedTargetDistance;
|
||||
public float ObstructedDistance;
|
||||
public float PitchAngle;
|
||||
public float3 PlanarForward;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct OrbitCameraControl : IComponentData
|
||||
{
|
||||
public Entity FollowedCharacterEntity;
|
||||
public float2 LookDegreesDelta;
|
||||
public float ZoomDelta;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct OrbitCameraIgnoredEntityBufferElement : IBufferElementData
|
||||
{
|
||||
public Entity Entity;
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 441900b2dca2cda429cba5f372fcf5fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
using System.Collections.Generic;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
using UnityEngine;
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public class OrbitCameraAuthoring : MonoBehaviour
|
||||
{
|
||||
[Header("Rotation")]
|
||||
public float RotationSpeed = 2f;
|
||||
public float MaxVAngle = 89f;
|
||||
public float MinVAngle = -89f;
|
||||
public bool RotateWithCharacterParent = true;
|
||||
|
||||
[Header("Distance")]
|
||||
public float StartDistance = 5f;
|
||||
public float MinDistance = 0f;
|
||||
public float MaxDistance = 10f;
|
||||
public float DistanceMovementSpeed = 1f;
|
||||
public float DistanceMovementSharpness = 20f;
|
||||
|
||||
[Header("Obstructions")]
|
||||
public float ObstructionRadius = 0.1f;
|
||||
public float ObstructionInnerSmoothingSharpness = float.MaxValue;
|
||||
public float ObstructionOuterSmoothingSharpness = 5f;
|
||||
public bool PreventFixedUpdateJitter = true;
|
||||
|
||||
[Header("Misc")]
|
||||
public List<GameObject> IgnoredEntities = new List<GameObject>();
|
||||
|
||||
public class Baker : Baker<OrbitCameraAuthoring>
|
||||
{
|
||||
public override void Bake(OrbitCameraAuthoring authoring)
|
||||
{
|
||||
Entity entity = GetEntity(TransformUsageFlags.Dynamic | TransformUsageFlags.WorldSpace);
|
||||
|
||||
AddComponent(entity, new OrbitCamera
|
||||
{
|
||||
RotationSpeed = authoring.RotationSpeed,
|
||||
MaxVAngle = authoring.MaxVAngle,
|
||||
MinVAngle = authoring.MinVAngle,
|
||||
RotateWithCharacterParent = authoring.RotateWithCharacterParent,
|
||||
|
||||
MinDistance = authoring.MinDistance,
|
||||
MaxDistance = authoring.MaxDistance,
|
||||
DistanceMovementSpeed = authoring.DistanceMovementSpeed,
|
||||
DistanceMovementSharpness = authoring.DistanceMovementSharpness,
|
||||
|
||||
ObstructionRadius = authoring.ObstructionRadius,
|
||||
ObstructionInnerSmoothingSharpness = authoring.ObstructionInnerSmoothingSharpness,
|
||||
ObstructionOuterSmoothingSharpness = authoring.ObstructionOuterSmoothingSharpness,
|
||||
PreventFixedUpdateJitter = authoring.PreventFixedUpdateJitter,
|
||||
|
||||
TargetDistance = authoring.StartDistance,
|
||||
SmoothedTargetDistance = authoring.StartDistance,
|
||||
ObstructedDistance = authoring.StartDistance,
|
||||
|
||||
PitchAngle = 0f,
|
||||
PlanarForward = -math.forward(),
|
||||
});
|
||||
|
||||
AddComponent(entity, new OrbitCameraControl());
|
||||
|
||||
DynamicBuffer<OrbitCameraIgnoredEntityBufferElement> ignoredEntitiesBuffer = AddBuffer<OrbitCameraIgnoredEntityBufferElement>(entity);
|
||||
for (int i = 0; i < authoring.IgnoredEntities.Count; i++)
|
||||
{
|
||||
ignoredEntitiesBuffer.Add(new OrbitCameraIgnoredEntityBufferElement
|
||||
{
|
||||
Entity = GetEntity(authoring.IgnoredEntities[i], TransformUsageFlags.None),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70c323b4be4b1fa4089d1a1fd2872754
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+367
@@ -0,0 +1,367 @@
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Physics;
|
||||
using Unity.Transforms;
|
||||
using Unity.CharacterController;
|
||||
|
||||
[UpdateInGroup(typeof(SimulationSystemGroup))]
|
||||
[UpdateAfter(typeof(FixedStepSimulationSystemGroup))]
|
||||
[UpdateAfter(typeof(ThirdPersonPlayerVariableStepControlSystem))]
|
||||
[UpdateAfter(typeof(ThirdPersonCharacterVariableUpdateSystem))]
|
||||
[UpdateBefore(typeof(TransformSystemGroup))]
|
||||
[BurstCompile]
|
||||
public partial struct OrbitCameraSimulationSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
state.RequireForUpdate(SystemAPI.QueryBuilder().WithAll<OrbitCamera, OrbitCameraControl>().Build());
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
OrbitCameraSimulationJob job = new OrbitCameraSimulationJob
|
||||
{
|
||||
DeltaTime = SystemAPI.Time.DeltaTime,
|
||||
LocalTransformLookup = SystemAPI.GetComponentLookup<LocalTransform>(false),
|
||||
ParentLookup = SystemAPI.GetComponentLookup<Parent>(true),
|
||||
PostTransformMatrixLookup = SystemAPI.GetComponentLookup<PostTransformMatrix>(true),
|
||||
CameraTargetLookup = SystemAPI.GetComponentLookup<CameraTarget>(true),
|
||||
KinematicCharacterBodyLookup = SystemAPI.GetComponentLookup<KinematicCharacterBody>(true),
|
||||
};
|
||||
job.Schedule();
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
[WithAll(typeof(Simulate))]
|
||||
public partial struct OrbitCameraSimulationJob : IJobEntity
|
||||
{
|
||||
public float DeltaTime;
|
||||
|
||||
public ComponentLookup<LocalTransform> LocalTransformLookup;
|
||||
[ReadOnly] public ComponentLookup<Parent> ParentLookup;
|
||||
[ReadOnly] public ComponentLookup<PostTransformMatrix> PostTransformMatrixLookup;
|
||||
[ReadOnly] public ComponentLookup<CameraTarget> CameraTargetLookup;
|
||||
[ReadOnly] public ComponentLookup<KinematicCharacterBody> KinematicCharacterBodyLookup;
|
||||
|
||||
void Execute(Entity entity, ref OrbitCamera orbitCamera, in OrbitCameraControl cameraControl)
|
||||
{
|
||||
if (OrbitCameraUtilities.TryGetCameraTargetSimulationWorldTransform(
|
||||
cameraControl.FollowedCharacterEntity,
|
||||
ref LocalTransformLookup,
|
||||
ref ParentLookup,
|
||||
ref PostTransformMatrixLookup,
|
||||
ref CameraTargetLookup,
|
||||
out float4x4 targetWorldTransform))
|
||||
{
|
||||
float3 targetUp = targetWorldTransform.Up();
|
||||
float3 targetPosition = targetWorldTransform.Translation();
|
||||
|
||||
// Update planar forward based on target up direction and rotation from parent
|
||||
{
|
||||
quaternion tmpPlanarRotation = MathUtilities.CreateRotationWithUpPriority(targetUp, orbitCamera.PlanarForward);
|
||||
|
||||
// Rotation from character parent
|
||||
if (orbitCamera.RotateWithCharacterParent &&
|
||||
KinematicCharacterBodyLookup.TryGetComponent(cameraControl.FollowedCharacterEntity, out KinematicCharacterBody characterBody))
|
||||
{
|
||||
// Only consider rotation around the character up, since the camera is already adjusting itself to character up
|
||||
quaternion planarRotationFromParent = characterBody.RotationFromParent;
|
||||
KinematicCharacterUtilities.AddVariableRateRotationFromFixedRateRotation(ref tmpPlanarRotation, planarRotationFromParent, DeltaTime, characterBody.LastPhysicsUpdateDeltaTime);
|
||||
}
|
||||
|
||||
orbitCamera.PlanarForward = MathUtilities.GetForwardFromRotation(tmpPlanarRotation);
|
||||
}
|
||||
|
||||
// Yaw
|
||||
float yawAngleChange = cameraControl.LookDegreesDelta.x * orbitCamera.RotationSpeed;
|
||||
quaternion yawRotation = quaternion.Euler(targetUp * math.radians(yawAngleChange));
|
||||
orbitCamera.PlanarForward = math.rotate(yawRotation, orbitCamera.PlanarForward);
|
||||
|
||||
// Pitch
|
||||
orbitCamera.PitchAngle += -cameraControl.LookDegreesDelta.y * orbitCamera.RotationSpeed;
|
||||
orbitCamera.PitchAngle = math.clamp(orbitCamera.PitchAngle, orbitCamera.MinVAngle, orbitCamera.MaxVAngle);
|
||||
|
||||
// Calculate final rotation
|
||||
quaternion cameraRotation = OrbitCameraUtilities.CalculateCameraRotation(targetUp, orbitCamera.PlanarForward, orbitCamera.PitchAngle);
|
||||
|
||||
// Distance input
|
||||
float desiredDistanceMovementFromInput = cameraControl.ZoomDelta * orbitCamera.DistanceMovementSpeed;
|
||||
orbitCamera.TargetDistance = math.clamp(orbitCamera.TargetDistance + desiredDistanceMovementFromInput, orbitCamera.MinDistance, orbitCamera.MaxDistance);
|
||||
|
||||
// Calculate camera position (no smoothing or obstructions yet; these are done in the camera late update)
|
||||
float3 cameraPosition = OrbitCameraUtilities.CalculateCameraPosition(targetPosition, cameraRotation, orbitCamera.TargetDistance);
|
||||
|
||||
// Write back to component
|
||||
LocalTransformLookup[entity] = LocalTransform.FromPositionRotation(cameraPosition, cameraRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UpdateInGroup(typeof(SimulationSystemGroup))]
|
||||
[UpdateAfter(typeof(TransformSystemGroup))]
|
||||
[BurstCompile]
|
||||
public partial struct OrbitCameraLateUpdateSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
state.RequireForUpdate<PhysicsWorldSingleton>();
|
||||
state.RequireForUpdate(SystemAPI.QueryBuilder().WithAll<OrbitCamera, OrbitCameraControl>().Build());
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
OrbitCameraLateUpdateJob job = new OrbitCameraLateUpdateJob
|
||||
{
|
||||
DeltaTime = SystemAPI.Time.DeltaTime,
|
||||
PhysicsWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>().PhysicsWorld,
|
||||
LocalToWorldLookup = SystemAPI.GetComponentLookup<LocalToWorld>(false),
|
||||
CameraTargetLookup = SystemAPI.GetComponentLookup<CameraTarget>(true),
|
||||
KinematicCharacterBodyLookup = SystemAPI.GetComponentLookup<KinematicCharacterBody>(true),
|
||||
};
|
||||
job.Schedule();
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
[WithAll(typeof(Simulate))]
|
||||
public partial struct OrbitCameraLateUpdateJob : IJobEntity
|
||||
{
|
||||
public float DeltaTime;
|
||||
[ReadOnly]
|
||||
public PhysicsWorld PhysicsWorld;
|
||||
|
||||
public ComponentLookup<LocalToWorld> LocalToWorldLookup;
|
||||
[ReadOnly]
|
||||
public ComponentLookup<CameraTarget> CameraTargetLookup;
|
||||
[ReadOnly]
|
||||
public ComponentLookup<KinematicCharacterBody> KinematicCharacterBodyLookup;
|
||||
|
||||
void Execute(
|
||||
Entity entity,
|
||||
ref OrbitCamera orbitCamera,
|
||||
in OrbitCameraControl cameraControl,
|
||||
in DynamicBuffer<OrbitCameraIgnoredEntityBufferElement> ignoredEntitiesBuffer)
|
||||
{
|
||||
if (OrbitCameraUtilities.TryGetCameraTargetInterpolatedWorldTransform(
|
||||
cameraControl.FollowedCharacterEntity,
|
||||
ref LocalToWorldLookup,
|
||||
ref CameraTargetLookup,
|
||||
out LocalToWorld targetWorldTransform))
|
||||
{
|
||||
quaternion cameraRotation = OrbitCameraUtilities.CalculateCameraRotation(targetWorldTransform.Up, orbitCamera.PlanarForward, orbitCamera.PitchAngle);
|
||||
|
||||
float3 cameraForward = math.mul(cameraRotation, math.forward());
|
||||
float3 targetPosition = targetWorldTransform.Position;
|
||||
|
||||
// Distance smoothing
|
||||
orbitCamera.SmoothedTargetDistance = math.lerp(orbitCamera.SmoothedTargetDistance, orbitCamera.TargetDistance, MathUtilities.GetSharpnessInterpolant(orbitCamera.DistanceMovementSharpness, DeltaTime));
|
||||
|
||||
// Obstruction handling
|
||||
// Obstruction detection is handled here, because we have to adjust the obstruction distance
|
||||
// to match the interpolated physics body transform (as opposed to the "simulation" transform). Otherwise, a
|
||||
// camera getting obstructed by a moving physics body would have visible jitter.
|
||||
if (orbitCamera.ObstructionRadius > 0f)
|
||||
{
|
||||
float obstructionCheckDistance = orbitCamera.SmoothedTargetDistance;
|
||||
|
||||
CameraObstructionHitsCollector collector = new CameraObstructionHitsCollector(cameraControl.FollowedCharacterEntity, ignoredEntitiesBuffer, cameraForward);
|
||||
PhysicsWorld.SphereCastCustom(
|
||||
targetPosition,
|
||||
orbitCamera.ObstructionRadius,
|
||||
-cameraForward,
|
||||
obstructionCheckDistance,
|
||||
ref collector,
|
||||
CollisionFilter.Default,
|
||||
QueryInteraction.IgnoreTriggers);
|
||||
|
||||
float newObstructedDistance = obstructionCheckDistance;
|
||||
if (collector.NumHits > 0)
|
||||
{
|
||||
newObstructedDistance = obstructionCheckDistance * collector.ClosestHit.Fraction;
|
||||
|
||||
// Redo cast with the interpolated body transform to prevent FixedUpdate jitter in obstruction detection
|
||||
if (orbitCamera.PreventFixedUpdateJitter)
|
||||
{
|
||||
RigidBody hitBody = PhysicsWorld.Bodies[collector.ClosestHit.RigidBodyIndex];
|
||||
if (LocalToWorldLookup.TryGetComponent(hitBody.Entity, out LocalToWorld hitBodyLocalToWorld))
|
||||
{
|
||||
// Adjust the rigidbody transform for interpolation, so we can raycast it in that state
|
||||
hitBody.WorldFromBody = new RigidTransform(quaternion.LookRotationSafe(hitBodyLocalToWorld.Forward, hitBodyLocalToWorld.Up), hitBodyLocalToWorld.Position);
|
||||
|
||||
collector = new CameraObstructionHitsCollector(cameraControl.FollowedCharacterEntity, ignoredEntitiesBuffer, cameraForward);
|
||||
hitBody.SphereCastCustom(
|
||||
targetPosition,
|
||||
orbitCamera.ObstructionRadius,
|
||||
-cameraForward,
|
||||
obstructionCheckDistance,
|
||||
ref collector,
|
||||
CollisionFilter.Default,
|
||||
QueryInteraction.IgnoreTriggers);
|
||||
|
||||
if (collector.NumHits > 0)
|
||||
{
|
||||
newObstructedDistance = obstructionCheckDistance * collector.ClosestHit.Fraction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update current distance based on obstructed distance
|
||||
if (orbitCamera.ObstructedDistance < newObstructedDistance)
|
||||
{
|
||||
// Move outer
|
||||
orbitCamera.ObstructedDistance = math.lerp(orbitCamera.ObstructedDistance, newObstructedDistance, MathUtilities.GetSharpnessInterpolant(orbitCamera.ObstructionOuterSmoothingSharpness, DeltaTime));
|
||||
}
|
||||
else if (orbitCamera.ObstructedDistance > newObstructedDistance)
|
||||
{
|
||||
// Move inner
|
||||
orbitCamera.ObstructedDistance = math.lerp(orbitCamera.ObstructedDistance, newObstructedDistance, MathUtilities.GetSharpnessInterpolant(orbitCamera.ObstructionInnerSmoothingSharpness, DeltaTime));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
orbitCamera.ObstructedDistance = orbitCamera.SmoothedTargetDistance;
|
||||
}
|
||||
|
||||
// Place camera at the final distance (includes smoothing and obstructions)
|
||||
float3 cameraPosition = OrbitCameraUtilities.CalculateCameraPosition(targetPosition, cameraRotation, orbitCamera.ObstructedDistance);
|
||||
|
||||
// Write to LtW
|
||||
LocalToWorldLookup[entity] = new LocalToWorld { Value = new float4x4(cameraRotation, cameraPosition) };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class OrbitCameraUtilities
|
||||
{
|
||||
public static bool TryGetCameraTargetSimulationWorldTransform(
|
||||
Entity targetCharacterEntity,
|
||||
ref ComponentLookup<LocalTransform> localTransformLookup,
|
||||
ref ComponentLookup<Parent> parentLookup,
|
||||
ref ComponentLookup<PostTransformMatrix> postTransformMatrixLookup,
|
||||
ref ComponentLookup<CameraTarget> cameraTargetLookup,
|
||||
out float4x4 worldTransform)
|
||||
{
|
||||
bool foundValidCameraTarget = false;
|
||||
worldTransform = float4x4.identity;
|
||||
|
||||
// Camera target is either defined by the CameraTarget component, or if not, the transform of the followed character
|
||||
if (cameraTargetLookup.TryGetComponent(targetCharacterEntity, out CameraTarget cameraTarget) &&
|
||||
localTransformLookup.HasComponent(cameraTarget.TargetEntity))
|
||||
{
|
||||
TransformHelpers.ComputeWorldTransformMatrix(
|
||||
cameraTarget.TargetEntity,
|
||||
out worldTransform,
|
||||
ref localTransformLookup,
|
||||
ref parentLookup,
|
||||
ref postTransformMatrixLookup);
|
||||
foundValidCameraTarget = true;
|
||||
}
|
||||
else if (localTransformLookup.TryGetComponent(targetCharacterEntity, out LocalTransform characterLocalTransform))
|
||||
{
|
||||
worldTransform = float4x4.TRS(characterLocalTransform.Position, characterLocalTransform.Rotation, 1f);
|
||||
foundValidCameraTarget = true;
|
||||
}
|
||||
|
||||
return foundValidCameraTarget;
|
||||
}
|
||||
|
||||
public static bool TryGetCameraTargetInterpolatedWorldTransform(
|
||||
Entity targetCharacterEntity,
|
||||
ref ComponentLookup<LocalToWorld> localToWorldLookup,
|
||||
ref ComponentLookup<CameraTarget> cameraTargetLookup,
|
||||
out LocalToWorld worldTransform)
|
||||
{
|
||||
bool foundValidCameraTarget = false;
|
||||
worldTransform = default;
|
||||
|
||||
// Get the interpolated transform of the target
|
||||
if (cameraTargetLookup.TryGetComponent(targetCharacterEntity, out CameraTarget cameraTarget) &&
|
||||
localToWorldLookup.TryGetComponent(cameraTarget.TargetEntity, out worldTransform))
|
||||
{
|
||||
foundValidCameraTarget = true;
|
||||
}
|
||||
else if (localToWorldLookup.TryGetComponent(targetCharacterEntity, out worldTransform))
|
||||
{
|
||||
foundValidCameraTarget = true;
|
||||
}
|
||||
|
||||
return foundValidCameraTarget;
|
||||
}
|
||||
|
||||
public static quaternion CalculateCameraRotation(float3 targetUp, float3 planarForward, float pitchAngle)
|
||||
{
|
||||
quaternion pitchRotation = quaternion.Euler(math.right() * math.radians(pitchAngle));
|
||||
quaternion cameraRotation = MathUtilities.CreateRotationWithUpPriority(targetUp, planarForward);
|
||||
cameraRotation = math.mul(cameraRotation, pitchRotation);
|
||||
return cameraRotation;
|
||||
}
|
||||
|
||||
public static float3 CalculateCameraPosition(float3 targetPosition, quaternion cameraRotation, float distance)
|
||||
{
|
||||
return targetPosition + (-MathUtilities.GetForwardFromRotation(cameraRotation) * distance);
|
||||
}
|
||||
}
|
||||
|
||||
public struct CameraObstructionHitsCollector : ICollector<ColliderCastHit>
|
||||
{
|
||||
public bool EarlyOutOnFirstHit => false;
|
||||
public float MaxFraction => 1f;
|
||||
public int NumHits { get; private set; }
|
||||
|
||||
public ColliderCastHit ClosestHit;
|
||||
|
||||
private float _closestHitFraction;
|
||||
private float3 _cameraDirection;
|
||||
private Entity _followedCharacter;
|
||||
private DynamicBuffer<OrbitCameraIgnoredEntityBufferElement> _ignoredEntitiesBuffer;
|
||||
|
||||
public CameraObstructionHitsCollector(Entity followedCharacter, DynamicBuffer<OrbitCameraIgnoredEntityBufferElement> ignoredEntitiesBuffer, float3 cameraDirection)
|
||||
{
|
||||
NumHits = 0;
|
||||
ClosestHit = default;
|
||||
|
||||
_closestHitFraction = float.MaxValue;
|
||||
_cameraDirection = cameraDirection;
|
||||
_followedCharacter = followedCharacter;
|
||||
_ignoredEntitiesBuffer = ignoredEntitiesBuffer;
|
||||
}
|
||||
|
||||
public bool AddHit(ColliderCastHit hit)
|
||||
{
|
||||
if (_followedCharacter == hit.Entity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (math.dot(hit.SurfaceNormal, _cameraDirection) < 0f || !PhysicsUtilities.IsCollidable(hit.Material))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _ignoredEntitiesBuffer.Length; i++)
|
||||
{
|
||||
if (_ignoredEntitiesBuffer[i].Entity == hit.Entity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Process valid hit
|
||||
if (hit.Fraction < _closestHitFraction)
|
||||
{
|
||||
_closestHitFraction = hit.Fraction;
|
||||
ClosestHit = hit;
|
||||
}
|
||||
NumHits++;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d6d36bc694f390408f5683be8de8c7d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in new issue
Block a user