Iteration 4 over Assets/Scripts (no component/file splits, no Unity assets touched): Dedup: - Route inline cursor-release, material guards, Ctrl-held and undo/redo input through existing InputUtil / SetMatFloat helpers - Add ungated InputUtil.KeyPressedThisFrame; GameplayKeyPressed builds on it - Unify FindDeep/FindDeepChild into GeometryUtil.FindDeep Dead code / stale docs: - Remove unused code-gen bake path (HsvColorPicker.Build, PaintHud factory) - Drop unreferenced symbols (SubPhaseChanged event, LocalPhaseDuration, IsLocalSceneMain, MouseSensitivity.Changed, IsPaused, InSession, NetworkControlled, PreviousPose, JointCount, voxel-count accessors) - Fix incorrect PlayerRole / PaintHud / Pick / PlayerPose docs Perf / robustness (behaviour-neutral): - ConcealmentMeter.Evaluate: reuse vertex/topology buffers, two-pointer crossing count - BuildMeshCaches: alloc-free vertex copy, cached topology/UVs - Guard all PlayerPaintSync LogSync sites behind logSync - Cache LocalViewerIsHunter / controller / CanShoot / TypingGuard lookups; dedup LocalIsHunter with MatchHud - Change-guard RefreshEmissionColor and HeroCutout.Disarm - Cache scene/countdown string comparisons per frame - Grow NonAlloc buffers and log-once on saturation Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
90 lines
4.8 KiB
C#
90 lines
4.8 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// A selectable player pose: an idle <see cref="AnimationClip"/> held while the player stands still,
|
|
/// plus optional walk and run clips that the pose system plays itself (the Animator stays empty) while
|
|
/// moving on the ground, its own CharacterController capsule dimensions (so a low pose like a ball can
|
|
/// crawl under furniture the default standing capsule is too tall for), and a camera-target y-offset that
|
|
/// frames the pose without moving the body.
|
|
///
|
|
/// Named PlayerPose (not Pose) to avoid shadowing the built-in UnityEngine.Pose struct, mirroring
|
|
/// why the controller is PlayerCharacterController and not just "PlayerController".
|
|
/// </summary>
|
|
[CreateAssetMenu(fileName = "NewPose", menuName = "Chameleon/Pose")]
|
|
public class PlayerPose : ScriptableObject
|
|
{
|
|
[Tooltip("Clip held while the player is idle in this pose (looped if the clip itself loops, " +
|
|
"otherwise frozen on its last frame). Authored for the paintman generic rig; clips for " +
|
|
"other hierarchies will not retarget.")]
|
|
[SerializeField] private AnimationClip clip;
|
|
|
|
[Tooltip("Playback speed multiplier for the idle clip. 1 = authored speed.")]
|
|
[Range(0.1f, 3f)]
|
|
[SerializeField] private float clipSpeed = 1f;
|
|
|
|
[Tooltip("Optional. Played instead of the idle clip while walking on the ground (moving, not " +
|
|
"sprinting). Leave empty to keep holding the idle pose while walking. Should loop.")]
|
|
[SerializeField] private AnimationClip walkClip;
|
|
|
|
[Tooltip("Playback speed multiplier for the walk clip. 1 = authored speed.")]
|
|
[Range(0.1f, 3f)]
|
|
[SerializeField] private float walkClipSpeed = 1f;
|
|
|
|
[Tooltip("Optional. Played instead of the idle clip while sprinting on the ground. Leave empty to " +
|
|
"keep holding the idle pose while sprinting. Should loop.")]
|
|
[SerializeField] private AnimationClip runClip;
|
|
|
|
[Tooltip("Playback speed multiplier for the run clip. 1 = authored speed.")]
|
|
[Range(0.1f, 3f)]
|
|
[SerializeField] private float runClipSpeed = 1f;
|
|
|
|
[Tooltip("Optional. Played instead of the idle clip while falling (airborne and descending past the " +
|
|
"controller's fall threshold). Leave empty to keep holding the idle pose while falling. Should loop.")]
|
|
[SerializeField] private AnimationClip fallClip;
|
|
|
|
[Tooltip("Playback speed multiplier for the fall clip. 1 = authored speed.")]
|
|
[Range(0.1f, 3f)]
|
|
[SerializeField] private float fallClipSpeed = 1f;
|
|
|
|
[Header("Collision")]
|
|
[Tooltip("CharacterController capsule center Y while this pose is active (meters, local space). Lower " +
|
|
"this together with Height so a short pose still rests its feet on the floor.")]
|
|
[SerializeField] private float controllerCenterY = 0.66f;
|
|
|
|
[Tooltip("CharacterController capsule radius while this pose is active (meters). Unity clamps it to " +
|
|
"half the height.")]
|
|
[Min(0.01f)]
|
|
[SerializeField] private float controllerRadius = 0.1f;
|
|
|
|
[Tooltip("CharacterController capsule height while this pose is active (meters). Lower it (with Center " +
|
|
"Y) so a ball/star pose can crawl under a table or couch the default capsule is too tall for.")]
|
|
[Min(0.01f)]
|
|
[SerializeField] private float controllerHeight = 1.3f;
|
|
|
|
[Tooltip("Local-up offset applied to the camera target (the ThirdPersonCamera's follow/look target) " +
|
|
"while this pose is active, in ANY state. Frames the pose by raising/lowering what the camera " +
|
|
"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;
|
|
|
|
// Read-only accessors; semantics are documented on the serialized fields' tooltips above.
|
|
public AnimationClip Clip => clip;
|
|
public float ClipSpeed => clipSpeed;
|
|
public AnimationClip WalkClip => walkClip;
|
|
public float WalkClipSpeed => walkClipSpeed;
|
|
public AnimationClip RunClip => runClip;
|
|
public float RunClipSpeed => runClipSpeed;
|
|
public AnimationClip FallClip => fallClip;
|
|
public float FallClipSpeed => fallClipSpeed;
|
|
public float ControllerCenterY => controllerCenterY;
|
|
public float ControllerRadius => controllerRadius;
|
|
public float ControllerHeight => controllerHeight;
|
|
public float CameraTargetYOffset => cameraTargetYOffset;
|
|
public float FirstPersonCameraTargetYOffset => firstPersonCameraTargetYOffset;
|
|
}
|