diff --git a/Assets/Poses/Pose_Ball.asset b/Assets/Poses/Pose_Ball.asset
index 426028f..06c8e94 100644
--- a/Assets/Poses/Pose_Ball.asset
+++ b/Assets/Poses/Pose_Ball.asset
@@ -22,3 +22,4 @@ MonoBehaviour:
controllerRadius: 0.15
controllerHeight: 0.5
cameraTargetYOffset: -0.5
+ firstPersonCameraTargetYOffset: -0.8
diff --git a/Assets/Poses/Pose_Sit.asset b/Assets/Poses/Pose_Sit.asset
index 25271eb..ca90d1c 100644
--- a/Assets/Poses/Pose_Sit.asset
+++ b/Assets/Poses/Pose_Sit.asset
@@ -22,3 +22,4 @@ MonoBehaviour:
controllerRadius: 0.1
controllerHeight: 0.85
cameraTargetYOffset: -0.2
+ firstPersonCameraTargetYOffset: -0.2
diff --git a/Assets/Poses/Pose_Star.asset b/Assets/Poses/Pose_Star.asset
index d473c34..f274ff2 100644
--- a/Assets/Poses/Pose_Star.asset
+++ b/Assets/Poses/Pose_Star.asset
@@ -22,3 +22,4 @@ MonoBehaviour:
controllerRadius: 0.1
controllerHeight: 0.3
cameraTargetYOffset: -0.55
+ firstPersonCameraTargetYOffset: -1.18
diff --git a/Assets/Prefabs/Hider.prefab b/Assets/Prefabs/Hider.prefab
new file mode 100644
index 0000000..e88df9f
--- /dev/null
+++ b/Assets/Prefabs/Hider.prefab
@@ -0,0 +1,79 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &488197323585957958
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: 273411532115212066, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: scale
+ value: 0.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 4587432968399885263, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_Enabled
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 5384024074013944205, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_Name
+ value: Player Variant
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 0.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 0.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 0.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
diff --git a/Assets/Prefabs/Hider.prefab.meta b/Assets/Prefabs/Hider.prefab.meta
new file mode 100644
index 0000000..81b5ad0
--- /dev/null
+++ b/Assets/Prefabs/Hider.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 6b0b58e8352625343951db00beb8cb0a
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Prefabs/Hunter.prefab b/Assets/Prefabs/Hunter.prefab
new file mode 100644
index 0000000..28515be
--- /dev/null
+++ b/Assets/Prefabs/Hunter.prefab
@@ -0,0 +1,75 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &8795081103086920006
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: 273411532115212066, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: scale
+ value: 2.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 5384024074013944205, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_Name
+ value: Hunter
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalScale.x
+ value: 2.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalScale.y
+ value: 2.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalScale.z
+ value: 2.5
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
diff --git a/Assets/Prefabs/Hunter.prefab.meta b/Assets/Prefabs/Hunter.prefab.meta
new file mode 100644
index 0000000..7c71314
--- /dev/null
+++ b/Assets/Prefabs/Hunter.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: cf153a3aea3d5da4f9d4cdbff0be8180
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Prefabs/Player.prefab b/Assets/Prefabs/Player.prefab
index b587e7d..c7cb008 100644
--- a/Assets/Prefabs/Player.prefab
+++ b/Assets/Prefabs/Player.prefab
@@ -126,8 +126,9 @@ MonoBehaviour:
poses:
- {fileID: 11400000, guid: 3b59c882f27d0d04a82d2db251af1728, type: 2}
- {fileID: 11400000, guid: 649ecccdabb7ef9438addcec6663b037, type: 2}
- - {fileID: 11400000, guid: 1545cfba9b5e06d41ae72c7ec766baaf, type: 2}
+ - {fileID: 11400000, guid: 90df501d86681394b834f647f6f4e939, type: 2}
- {fileID: 11400000, guid: c5cf9d420554e5e4e96d3bee1903967a, type: 2}
+ - {fileID: 11400000, guid: 1545cfba9b5e06d41ae72c7ec766baaf, type: 2}
defaultPoseIndex: 0
cycleKey: 17
poseBlendDuration: 0.2
@@ -233,6 +234,10 @@ PrefabInstance:
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
+ - target: {fileID: 3763709765074082564, guid: c2044ff1352a6bb4586d6d04b59012b7, type: 3}
+ propertyPath: m_TagString
+ value: Player
+ objectReference: {fileID: 0}
- target: {fileID: 5866666021909216657, guid: c2044ff1352a6bb4586d6d04b59012b7, type: 3}
propertyPath: m_Avatar
value:
diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity
index 28bb52e..d125683 100644
--- a/Assets/Scenes/SampleScene.unity
+++ b/Assets/Scenes/SampleScene.unity
@@ -603,7 +603,7 @@ MonoBehaviour:
TransparentLayers:
serializedVersion: 2
m_Bits: 0
- MinimumDistanceFromTarget: 0.8
+ MinimumDistanceFromTarget: 0.5
AvoidObstacles:
Enabled: 1
DistanceLimit: 0
@@ -614,7 +614,7 @@ MonoBehaviour:
YOffset: 0
Strategy: 0
MaximumEffort: 4
- SmoothingTime: 0
+ SmoothingTime: 0.05
Damping: 0.2
DampingWhenOccluded: 0.1
ShotQualityEvaluation:
@@ -735,11 +735,11 @@ MonoBehaviour:
m_StreamingVersion: 20241001
m_LegacyPriority: 0
Target:
- TrackingTarget: {fileID: 1774267802}
- LookAtTarget: {fileID: 1774267802}
+ TrackingTarget: {fileID: 5297240775790447668}
+ LookAtTarget: {fileID: 0}
CustomLookAtTarget: 0
Lens:
- FieldOfView: 40
+ FieldOfView: 45
OrthographicSize: 10
NearClipPlane: 0.1
FarClipPlane: 5000
@@ -767,7 +767,7 @@ Transform:
m_GameObject: {fileID: 172071430}
serializedVersion: 2
m_LocalRotation: {x: 0.1305262, y: 2.1996925e-11, z: -4.1198815e-12, w: 0.9914449}
- m_LocalPosition: {x: 0, y: 1.5396858, z: -4.3466663}
+ m_LocalPosition: {x: 0, y: 3.0396857, z: -4.3466663}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@@ -1453,7 +1453,7 @@ Camera:
height: 1
near clip plane: 0.1
far clip plane: 5000
- field of view: 40
+ field of view: 45
orthographic: 0
orthographic size: 10
m_Depth: -1
@@ -1480,7 +1480,7 @@ Transform:
m_GameObject: {fileID: 330585543}
serializedVersion: 2
m_LocalRotation: {x: 0.1305262, y: 2.1832952e-11, z: -2.8743629e-12, w: 0.9914449}
- m_LocalPosition: {x: 0, y: 1.5396858, z: -4.3466663}
+ m_LocalPosition: {x: 0, y: 3.0396857, z: -4.3466663}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
@@ -2246,6 +2246,19 @@ Transform:
m_CorrespondingSourceObject: {fileID: 433010, guid: ac92cfb4db971489da14157130119008, type: 3}
m_PrefabInstance: {fileID: 505084142}
m_PrefabAsset: {fileID: 0}
+--- !u!134 &539493728
+PhysicsMaterial:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: ' (Instance)'
+ serializedVersion: 2
+ m_DynamicFriction: 0.6
+ m_StaticFriction: 0.6
+ m_Bounciness: 0
+ m_FrictionCombine: 0
+ m_BounceCombine: 0
--- !u!1001 &551852894
PrefabInstance:
m_ObjectHideFlags: 0
@@ -2498,6 +2511,104 @@ Transform:
m_CorrespondingSourceObject: {fileID: 477104, guid: 6aacb349af157442ebc4e122e8d6b9bd, type: 3}
m_PrefabInstance: {fileID: 580280589}
m_PrefabAsset: {fileID: 0}
+--- !u!1 &582951479
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 582951482}
+ - component: {fileID: 582951481}
+ - component: {fileID: 582951480}
+ m_Layer: 0
+ m_Name: FirstPersonCamera
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &582951480
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 582951479}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 43b8f1dc43642294f99fab0aaabf6197, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::FirstPersonController
+ cameraTarget: {fileID: 897939465}
+ hiddenRenderers:
+ - {fileID: 1294962561}
+ horizontalSensitivity: 0.1
+ verticalSensitivity: 0.075
+ invertY: 0
+ maxPitch: 89
+ lookSmoothTime: 0.04
+ activePriority: 100
+ inactivePriority: -100
+--- !u!114 &582951481
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 582951479}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: f9dfa5b682dcd46bda6128250e975f58, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Unity.Cinemachine::Unity.Cinemachine.CinemachineCamera
+ Priority:
+ Enabled: 1
+ m_Value: -100
+ OutputChannel: 1
+ StandbyUpdate: 2
+ m_StreamingVersion: 20241001
+ m_LegacyPriority: 0
+ Target:
+ TrackingTarget: {fileID: 0}
+ LookAtTarget: {fileID: 0}
+ CustomLookAtTarget: 0
+ Lens:
+ FieldOfView: 45
+ OrthographicSize: 10
+ NearClipPlane: 0.1
+ FarClipPlane: 5000
+ Dutch: 0
+ ModeOverride: 0
+ PhysicalProperties:
+ GateFit: 2
+ SensorSize: {x: 21.946, y: 16.002}
+ LensShift: {x: 0, y: 0}
+ FocusDistance: 10
+ Iso: 200
+ ShutterSpeed: 0.005
+ Aperture: 16
+ BladeCount: 5
+ Curvature: {x: 2, y: 11}
+ BarrelClipping: 0.25
+ Anamorphism: 0
+ BlendHint: 0
+--- !u!4 &582951482
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 582951479}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 1.875, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &607565146
PrefabInstance:
m_ObjectHideFlags: 0
@@ -2559,19 +2670,6 @@ PrefabInstance:
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ac1cc01cb5dbf5d4f869c403b38f8a21, type: 3}
---- !u!134 &610463647
-PhysicsMaterial:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name:
- serializedVersion: 2
- m_DynamicFriction: 0.6
- m_StaticFriction: 0.6
- m_Bounciness: 0
- m_FrictionCombine: 0
- m_BounceCombine: 0
--- !u!1001 &626957352
PrefabInstance:
m_ObjectHideFlags: 0
@@ -3965,6 +4063,37 @@ MeshCollider:
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 4300000, guid: 6d5becbf770f24fa3ab1ceaba45fcefa, type: 3}
+--- !u!1 &897939464
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 897939465}
+ m_Layer: 0
+ m_Name: FirstPersonTarget
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &897939465
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 897939464}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 1.2, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 1141039639}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &924705986
PrefabInstance:
m_ObjectHideFlags: 0
@@ -4530,10 +4659,15 @@ Transform:
m_CorrespondingSourceObject: {fileID: 411130, guid: a4bb788560e5d4617b970cd301097f38, type: 3}
m_PrefabInstance: {fileID: 1039758568}
m_PrefabAsset: {fileID: 0}
+--- !u!4 &1141039639 stripped
+Transform:
+ m_CorrespondingSourceObject: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ m_PrefabInstance: {fileID: 5297240775790447667}
+ m_PrefabAsset: {fileID: 0}
--- !u!114 &1141039642 stripped
MonoBehaviour:
- m_CorrespondingSourceObject: {fileID: 1035623159758896108, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- m_PrefabInstance: {fileID: 2016604527338364568}
+ m_CorrespondingSourceObject: {fileID: 8381518232634759850, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ m_PrefabInstance: {fileID: 5297240775790447667}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
@@ -4934,7 +5068,7 @@ CharacterController:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1282734303}
- m_Material: {fileID: 610463647}
+ m_Material: {fileID: 539493728}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
@@ -4976,7 +5110,7 @@ MonoBehaviour:
LookAtTarget: {fileID: 0}
CustomLookAtTarget: 0
Lens:
- FieldOfView: 40
+ FieldOfView: 45
OrthographicSize: 10
NearClipPlane: 0.1
FarClipPlane: 5000
@@ -5010,6 +5144,11 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!137 &1294962561 stripped
+SkinnedMeshRenderer:
+ m_CorrespondingSourceObject: {fileID: 8001664246499114791, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ m_PrefabInstance: {fileID: 5297240775790447667}
+ m_PrefabAsset: {fileID: 0}
--- !u!1001 &1317768121
PrefabInstance:
m_ObjectHideFlags: 0
@@ -5800,6 +5939,7 @@ MonoBehaviour:
cameraInput: {fileID: 172071431}
painter: {fileID: 0}
freeCam: {fileID: 1282734304}
+ firstPerson: {fileID: 582951480}
switchKey: 3
startModeIndex: 0
--- !u!4 &1516578028
@@ -6824,11 +6964,6 @@ Transform:
m_CorrespondingSourceObject: {fileID: 468598, guid: 0525b7ad910d145f9a39a0da3b697815, type: 3}
m_PrefabInstance: {fileID: 1762911884}
m_PrefabAsset: {fileID: 0}
---- !u!4 &1774267802 stripped
-Transform:
- m_CorrespondingSourceObject: {fileID: 4348940595172967010, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- m_PrefabInstance: {fileID: 2016604527338364568}
- m_PrefabAsset: {fileID: 0}
--- !u!1001 &1797333846
PrefabInstance:
m_ObjectHideFlags: 0
@@ -7678,7 +7813,7 @@ Transform:
m_CorrespondingSourceObject: {fileID: 4922444305696846, guid: ac1cc01cb5dbf5d4f869c403b38f8a21, type: 3}
m_PrefabInstance: {fileID: 1424346480}
m_PrefabAsset: {fileID: 0}
---- !u!1001 &2016604527338364568
+--- !u!1001 &5297240775790447667
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
@@ -7686,95 +7821,71 @@ PrefabInstance:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- - target: {fileID: 273411532115212066, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: scale
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 1514890176713383521, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: m_Enabled
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 4587432968399885263, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: poses.Array.size
- value: 5
- objectReference: {fileID: 0}
- - target: {fileID: 4587432968399885263, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: 'poses.Array.data[2]'
- value:
- objectReference: {fileID: 11400000, guid: 90df501d86681394b834f647f6f4e939, type: 2}
- - target: {fileID: 4587432968399885263, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: 'poses.Array.data[3]'
- value:
- objectReference: {fileID: 11400000, guid: c5cf9d420554e5e4e96d3bee1903967a, type: 2}
- - target: {fileID: 4587432968399885263, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: 'poses.Array.data[4]'
- value:
- objectReference: {fileID: 11400000, guid: 1545cfba9b5e06d41ae72c7ec766baaf, type: 2}
- - target: {fileID: 5280718916654756701, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: m_IsActive
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 5384024074013944205, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: m_Name
- value: Player
- objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: m_LocalScale.x
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: m_LocalScale.y
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
- propertyPath: m_LocalScale.z
- value: 0.5
- objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 6997860362608943113, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ - target: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
+ - target: {fileID: 3510981371713521867, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ propertyPath: m_Name
+ value: Player
+ objectReference: {fileID: 0}
+ - target: {fileID: 3510981371713521867, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ propertyPath: m_IsActive
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 8381518232634759850, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ propertyPath: sprintSpeedMultiplier
+ value: 2
+ objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
- m_AddedGameObjects: []
+ m_AddedGameObjects:
+ - targetCorrespondingSourceObject: {fileID: 1950906664192868687, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ insertIndex: -1
+ addedObject: {fileID: 897939465}
m_AddedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: 97017ed3bb40aff4e885440d9a7336ee, type: 3}
+ m_SourcePrefab: {fileID: 100100000, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+--- !u!4 &5297240775790447668 stripped
+Transform:
+ m_CorrespondingSourceObject: {fileID: 5067936922952835876, guid: cf153a3aea3d5da4f9d4cdbff0be8180, type: 3}
+ m_PrefabInstance: {fileID: 5297240775790447667}
+ m_PrefabAsset: {fileID: 0}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
@@ -7782,12 +7893,13 @@ SceneRoots:
- {fileID: 1516578028}
- {fileID: 2009475134}
- {fileID: 330585546}
+ - {fileID: 582951482}
- {fileID: 172071436}
- {fileID: 1282734307}
- {fileID: 832575519}
- {fileID: 410087041}
- {fileID: 2025317892}
- - {fileID: 2016604527338364568}
+ - {fileID: 5297240775790447667}
- {fileID: 686187287}
- {fileID: 489277934}
- {fileID: 347639557}
diff --git a/Assets/Scripts/FirstPersonController.cs b/Assets/Scripts/FirstPersonController.cs
new file mode 100644
index 0000000..2932e6d
--- /dev/null
+++ b/Assets/Scripts/FirstPersonController.cs
@@ -0,0 +1,214 @@
+using UnityEngine;
+using Unity.Cinemachine;
+#if ENABLE_INPUT_SYSTEM
+using UnityEngine.InputSystem;
+#endif
+
+///
+/// First-person camera. Drives its OWN dedicated : each frame it snaps
+/// to the player's CameraTarget (the same point the ThirdPersonCamera tracks) for position and
+/// applies free mouse-look (yaw/pitch) for rotation. While active the player's mesh is hidden so the
+/// body isn't seen from the inside. Movement stays with the player controller, which reads the
+/// brain-driven Main Camera forward, so WASD is automatically relative to this view.
+///
+/// Activation is driven by via : it raises the
+/// vcam priority so the CinemachineBrain blends to it, snaps look to the current view (no jump), hides
+/// the mesh and locks the cursor. While inactive the vcam rests at a low priority and this component
+/// does nothing.
+///
+[RequireComponent(typeof(CinemachineCamera))]
+[DisallowMultipleComponent]
+public class FirstPersonController : MonoBehaviour
+{
+ [Header("Target")]
+ [Tooltip("Eye position the camera sits at (the player's CameraTarget). Empty = auto-resolved from the player's \"CameraTarget\" child.")]
+ public Transform cameraTarget;
+
+ [Tooltip("Renderers hidden while first-person is active (so you don't see your own body). Empty = the player's SkinnedMeshRenderers, auto-resolved.")]
+ public Renderer[] hiddenRenderers;
+
+ [Header("Look")]
+ [Tooltip("Horizontal look sensitivity (degrees of yaw per pixel).")]
+ public float horizontalSensitivity = 0.2f;
+
+ [Tooltip("Vertical look sensitivity (degrees of pitch per pixel).")]
+ public float verticalSensitivity = 0.15f;
+
+ [Tooltip("Invert vertical look (mouse up tilts the camera down).")]
+ public bool invertY = false;
+
+ [Tooltip("Pitch is clamped to +/- this angle (degrees) so the camera never flips over.")]
+ [Range(1f, 89.9f)]
+ public float maxPitch = 89f;
+
+ [Header("Smoothing")]
+ [Tooltip("Look smoothing, in seconds. 0 = raw mouse (instant); small values take the edge off jitter without feeling laggy.")]
+ [Range(0f, 0.3f)]
+ public float lookSmoothTime = 0.04f;
+
+ [Header("Camera")]
+ [Tooltip("Priority the dedicated CinemachineCamera takes while active (must beat the gameplay camera).")]
+ public int activePriority = 100;
+
+ [Tooltip("Priority the dedicated CinemachineCamera rests at while inactive (must lose to the gameplay camera).")]
+ public int inactivePriority = -100;
+
+ CinemachineCamera _vcam;
+ PlayerCharacterController _player; // body whose yaw we pin to the camera while active
+ PlayerPoseController _poseController; // supplies the active pose's per-pose first-person eye offset
+ float _yaw; // look target (raw input accumulates here)
+ float _pitch;
+ float _displayYaw; // smoothed value actually applied to the transform
+ float _displayPitch;
+ float _yawSmoothRef;
+ float _pitchSmoothRef;
+ bool _resolved;
+
+ void Awake()
+ {
+ _vcam = GetComponent();
+ if (!_vcam)
+ Debug.LogError("[FirstPersonController] No CinemachineCamera on this GameObject; first-person cannot go live.", this);
+ else
+ _vcam.Priority = inactivePriority;
+
+ ResolveReferences();
+
+ // Dormant until FirstPersonMode enters; nothing reads input or moves the rig meanwhile.
+ enabled = false;
+ }
+
+ /// Enter/leave first-person. Raises/lowers the vcam priority, hides the player mesh, snaps
+ /// look to the live view and manages the cursor. Called by .
+ public void SetActive(bool active)
+ {
+ if (_vcam)
+ _vcam.Priority = active ? activePriority : inactivePriority;
+
+ SetMeshHidden(active);
+
+ if (active)
+ {
+ SyncToCurrentView();
+ SetCursorLocked(true);
+ ApplyTransform(); // place at the eye on the same frame so the blend starts from there
+ if (_player) _player.FaceYaw = _displayYaw; // body faces the camera from frame one
+ }
+ else
+ {
+ SetCursorLocked(false);
+ if (_player) _player.FaceYaw = null; // restore movement-facing
+ }
+
+ enabled = active;
+ }
+
+ void LateUpdate()
+ {
+ // LateUpdate so the player has already moved the CameraTarget this frame.
+ LookTick();
+ ApplyTransform();
+ if (_player) _player.FaceYaw = _displayYaw; // keep the body's yaw locked to the camera
+ }
+
+ void LookTick()
+ {
+ Vector2 delta = ReadMouseDelta();
+ _yaw += delta.x * horizontalSensitivity;
+ float vs = verticalSensitivity * (invertY ? 1f : -1f);
+ _pitch = Mathf.Clamp(_pitch + delta.y * vs, -maxPitch, maxPitch);
+
+ if (lookSmoothTime > 0f)
+ {
+ // SmoothDampAngle is frame-rate-independent and wraps yaw correctly.
+ _displayYaw = Mathf.SmoothDampAngle(_displayYaw, _yaw, ref _yawSmoothRef, lookSmoothTime);
+ _displayPitch = Mathf.SmoothDampAngle(_displayPitch, _pitch, ref _pitchSmoothRef, lookSmoothTime);
+ }
+ else
+ {
+ _displayYaw = _yaw;
+ _displayPitch = _pitch;
+ }
+ }
+
+ void ApplyTransform()
+ {
+ Quaternion rot = Quaternion.Euler(_displayPitch, _displayYaw, 0f);
+ if (cameraTarget)
+ {
+ // Sit at the shared camera target, then raise/lower the eye by the active pose's first-person
+ // offset. TransformVector keeps it in the target's local up and scales with the player (so it
+ // tracks PlayerScaler), without disturbing the target the ThirdPersonCamera shares.
+ Vector3 pos = cameraTarget.position;
+ float offset = _poseController ? _poseController.FirstPersonCameraYOffset : 0f;
+ if (offset != 0f)
+ pos += cameraTarget.TransformVector(Vector3.up * offset);
+ transform.SetPositionAndRotation(pos, rot);
+ }
+ else
+ transform.rotation = rot;
+ }
+
+ /// Seed look from the currently rendered view so going live produces no visible jump.
+ void SyncToCurrentView()
+ {
+ var cam = Camera.main;
+ if (cam)
+ {
+ Vector3 e = cam.transform.rotation.eulerAngles;
+ _yaw = e.y;
+ float p = e.x > 180f ? e.x - 360f : e.x;
+ _pitch = Mathf.Clamp(p, -maxPitch, maxPitch);
+ }
+
+ // Snap the smoothed state to the fresh pose so entering never lags/jumps to catch up.
+ _displayYaw = _yaw;
+ _displayPitch = _pitch;
+ _yawSmoothRef = 0f;
+ _pitchSmoothRef = 0f;
+ }
+
+ void SetMeshHidden(bool hidden)
+ {
+ if (hiddenRenderers == null) return;
+ foreach (var r in hiddenRenderers)
+ if (r) r.enabled = !hidden;
+ }
+
+ void ResolveReferences()
+ {
+ if (_resolved) return;
+ _resolved = true;
+
+ var player = FindFirstObjectByType(FindObjectsInactive.Include);
+ if (!player) return;
+ _player = player;
+
+ if (!_poseController)
+ _poseController = player.GetComponent();
+
+ if (!cameraTarget)
+ {
+ Transform t = player.transform.Find("CameraTarget");
+ if (t) cameraTarget = t;
+ }
+
+ if (hiddenRenderers == null || hiddenRenderers.Length == 0)
+ hiddenRenderers = player.GetComponentsInChildren(true);
+ }
+
+ Vector2 ReadMouseDelta()
+ {
+#if ENABLE_INPUT_SYSTEM
+ return Mouse.current != null ? Mouse.current.delta.ReadValue() : Vector2.zero;
+#else
+ return new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")) * 10f;
+#endif
+ }
+
+ static void SetCursorLocked(bool locked)
+ {
+ Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
+ Cursor.visible = !locked;
+ }
+}
diff --git a/Assets/Scripts/FirstPersonController.cs.meta b/Assets/Scripts/FirstPersonController.cs.meta
new file mode 100644
index 0000000..0c797b4
--- /dev/null
+++ b/Assets/Scripts/FirstPersonController.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 43b8f1dc43642294f99fab0aaabf6197
\ No newline at end of file
diff --git a/Assets/Scripts/FirstPersonMode.cs b/Assets/Scripts/FirstPersonMode.cs
new file mode 100644
index 0000000..e4a89df
--- /dev/null
+++ b/Assets/Scripts/FirstPersonMode.cs
@@ -0,0 +1,41 @@
+///
+/// First-person mode. The player keeps walking (WASD, camera-relative) but the camera moves to the
+/// player's eye (the CameraTarget) with free mouse-look, and the player's mesh is hidden so the body
+/// isn't seen from the inside. The orbit camera input is disabled while here so it doesn't fight for
+/// the cursor; the drives its own dedicated CinemachineCamera.
+///
+public class FirstPersonMode : GameMode
+{
+ public override string DisplayName => "First Person";
+
+ public override void Enter()
+ {
+ // Player stays fully controllable; only the view changes.
+ if (Manager.Player)
+ {
+ Manager.Player.enabled = true;
+ Manager.Player.ControlEnabled = true;
+ }
+
+ if (Manager.Painter)
+ Manager.Painter.PaintingEnabled = false;
+
+ // The orbit rig would otherwise keep grabbing the cursor and reading the mouse every frame.
+ if (Manager.CameraInput)
+ Manager.CameraInput.enabled = false;
+
+ if (Manager.FirstPerson)
+ Manager.FirstPerson.SetActive(true);
+ }
+
+ public override void Exit()
+ {
+ // Modes are Enter-only, so first-person must undo its own camera takeover (and unhide the mesh)
+ // here; the next mode's Enter restores the player/painter/look-mode state.
+ if (Manager.FirstPerson)
+ Manager.FirstPerson.SetActive(false);
+
+ if (Manager.CameraInput)
+ Manager.CameraInput.enabled = true;
+ }
+}
diff --git a/Assets/Scripts/FirstPersonMode.cs.meta b/Assets/Scripts/FirstPersonMode.cs.meta
new file mode 100644
index 0000000..3b1883c
--- /dev/null
+++ b/Assets/Scripts/FirstPersonMode.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: c514f1116e18b6c42907a5cb19aa228d
\ No newline at end of file
diff --git a/Assets/Scripts/GameModeManager.cs b/Assets/Scripts/GameModeManager.cs
index b136b2d..6f4cdab 100644
--- a/Assets/Scripts/GameModeManager.cs
+++ b/Assets/Scripts/GameModeManager.cs
@@ -25,6 +25,9 @@ public class GameModeManager : MonoBehaviour
[Tooltip("Free-fly spectator camera. Empty = found automatically. Absent = Free Cam is left out of the cycle.")]
public FreeCamController freeCam;
+ [Tooltip("First-person camera. Empty = found automatically. Absent = First Person is left out of the cycle.")]
+ public FirstPersonController firstPerson;
+
//[Tooltip("Insect / surface-walk controller. Empty = found automatically.")]
//public InsectController insect;
@@ -43,6 +46,7 @@ public class GameModeManager : MonoBehaviour
public ThirdPersonOrbitInput CameraInput => cameraInput;
public MeshPainter Painter => painter;
public FreeCamController FreeCam => freeCam;
+ public FirstPersonController FirstPerson => firstPerson;
//public InsectController Insect => insect;
/// Raised after a mode switch finishes (the new mode's Enter has already run).
@@ -63,6 +67,7 @@ public class GameModeManager : MonoBehaviour
if (!painter) painter = FindFirstObjectByType();
// Include inactive so a freecam rig that starts disabled is still found and wired.
if (!freeCam) freeCam = FindFirstObjectByType(FindObjectsInactive.Include);
+ if (!firstPerson) firstPerson = FindFirstObjectByType(FindObjectsInactive.Include);
//if (!insect) insect = FindFirstObjectByType();
BuildModes();
@@ -90,6 +95,10 @@ public class GameModeManager : MonoBehaviour
if (freeCam)
_modes.Add(new FreeCamMode());
+ // First Person only joins the cycle when a first-person rig is present, so scenes without one are unchanged.
+ if (firstPerson)
+ _modes.Add(new FirstPersonMode());
+
// Insect mode only joins the Tab cycle when a surface walker is present, so a scene
// without one behaves exactly as before (no dead, player-freezing mode in the cycle).
//if (insect)
diff --git a/Assets/Scripts/PlayerCharacterController.cs b/Assets/Scripts/PlayerCharacterController.cs
index f3f2206..4a800eb 100644
--- a/Assets/Scripts/PlayerCharacterController.cs
+++ b/Assets/Scripts/PlayerCharacterController.cs
@@ -147,6 +147,13 @@ public partial class PlayerCharacterController : MonoBehaviour
///
public bool ControlEnabled { get; set; } = true;
+ ///
+ /// When set, the body faces this world-space yaw (degrees) every frame instead of turning toward its
+ /// movement direction. First-person sets it so the character always faces where the camera looks;
+ /// null restores movement-facing. Only affects ground/air locomotion — wall-climb owns its own facing.
+ ///
+ public float? FaceYaw { get; set; }
+
/// True while in wall-climb mode.
public bool IsWallClimbing => _isWallClimbing;
@@ -425,8 +432,13 @@ public partial class PlayerCharacterController : MonoBehaviour
if (!_groundNormalUpdated)
_groundNormal = Vector3.up;
- // Face the movement direction, unless the right-button turn is actively steering the body.
- if (rotateTowardMovement && !groundYawDrag && moveDir.sqrMagnitude > 0.0001f)
+ // Facing: first-person pins the body to the camera yaw (even while idle); otherwise turn toward
+ // the movement direction, unless the right-button turn is actively steering the body.
+ if (FaceYaw.HasValue)
+ {
+ transform.rotation = Quaternion.Euler(0f, FaceYaw.Value, 0f);
+ }
+ else if (rotateTowardMovement && !groundYawDrag && moveDir.sqrMagnitude > 0.0001f)
{
Quaternion target = Quaternion.LookRotation(moveDir, Vector3.up);
transform.rotation = Quaternion.RotateTowards(
diff --git a/Assets/Scripts/PlayerPose.cs b/Assets/Scripts/PlayerPose.cs
index 382c54a..496d16b 100644
--- a/Assets/Scripts/PlayerPose.cs
+++ b/Assets/Scripts/PlayerPose.cs
@@ -58,6 +58,12 @@ public class PlayerPose : ScriptableObject
"tracks, without moving the body. Meters.")]
[SerializeField] private float cameraTargetYOffset;
+ [Tooltip("Additional local-up offset applied to the first-person eye (the FirstPersonController's camera " +
+ "position) while this pose is active, on top of the shared camera target. Only affects first " +
+ "person — never the body or the ThirdPersonCamera. Lets a low pose (ball/star) keep its eye at a " +
+ "sensible height even though the camera target sits where third-person frames it. Meters.")]
+ [SerializeField] private float firstPersonCameraTargetYOffset;
+
/// Idle clip held while the player stands still in this pose (may be null).
public AnimationClip Clip => clip;
@@ -87,4 +93,7 @@ public class PlayerPose : ScriptableObject
/// Local-up offset applied to the camera target while this pose is active (any state).
public float CameraTargetYOffset => cameraTargetYOffset;
+
+ /// Additional local-up offset for the first-person eye, on top of the camera target (first person only).
+ public float FirstPersonCameraTargetYOffset => firstPersonCameraTargetYOffset;
}
diff --git a/Assets/Scripts/PlayerPoseController.cs b/Assets/Scripts/PlayerPoseController.cs
index 0f66ce8..f947066 100644
--- a/Assets/Scripts/PlayerPoseController.cs
+++ b/Assets/Scripts/PlayerPoseController.cs
@@ -95,6 +95,7 @@ public partial class PlayerPoseController : MonoBehaviour
private bool _blending;
private float _cameraPoseOffset; // eased per-pose camera-target offset routed to the controller's camera target
+ private float _firstPersonCameraOffset; // eased per-pose first-person eye offset, read by the FirstPersonController (never written to the shared camera target)
// Capsule blend: the CharacterController dimensions are eased toward the active pose's via a single
// normalized blend (so the capsule stays a valid shape throughout) and written through the controller.
@@ -120,6 +121,9 @@ public partial class PlayerPoseController : MonoBehaviour
/// Index of the currently selected pose.
public int CurrentIndex => _currentIndex;
+ /// Eased per-pose y-offset for the first-person eye, applied on top of the camera target by the FirstPersonController.
+ public float FirstPersonCameraYOffset => _firstPersonCameraOffset;
+
void Awake()
{
_player = GetComponent();
@@ -178,6 +182,14 @@ public partial class PlayerPoseController : MonoBehaviour
? Mathf.MoveTowards(_cameraPoseOffset, cameraPoseTarget, cameraOffsetSpeed * Time.deltaTime)
: cameraPoseTarget;
_player.SetCameraTargetLocalYOffset(_cameraPoseOffset);
+
+ // First-person eye: a separate per-pose offset, eased the same way but NOT routed to the shared
+ // camera target (that would also move the ThirdPersonCamera). The FirstPersonController reads this
+ // and applies it to its own eye position only.
+ float firstPersonTarget = pose ? pose.FirstPersonCameraTargetYOffset : 0f;
+ _firstPersonCameraOffset = cameraOffsetSpeed > 0f
+ ? Mathf.MoveTowards(_firstPersonCameraOffset, firstPersonTarget, cameraOffsetSpeed * Time.deltaTime)
+ : firstPersonTarget;
}
void OnDisable()
@@ -186,6 +198,7 @@ public partial class PlayerPoseController : MonoBehaviour
// next idle frame. Also clear the camera offset and restore the default capsule we were holding.
ReleasePose();
_cameraPoseOffset = 0f;
+ _firstPersonCameraOffset = 0f;
if (_player)
{
_player.SetCameraTargetLocalYOffset(0f);