diff --git a/Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low Poly Character Collection 3 - Built-In.unitypackage.meta b/Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low Poly Character Collection 3 - Built-In.unitypackage.meta
new file mode 100644
index 0000000..f84d6fe
--- /dev/null
+++ b/Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low Poly Character Collection 3 - Built-In.unitypackage.meta
@@ -0,0 +1,15 @@
+fileFormatVersion: 2
+guid: fe35bb42b8a0bd144a6e5d1d670079ed
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 388758
+ packageName: Low Poly Character Collection 3
+ packageVersion: 1.1
+ assetPath: Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low
+ Poly Character Collection 3 - Built-In.unitypackage
+ uploadId: 946460
diff --git a/Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low Poly Character Collection 3 - HDRP.unitypackage.meta b/Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low Poly Character Collection 3 - HDRP.unitypackage.meta
new file mode 100644
index 0000000..0c49352
--- /dev/null
+++ b/Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low Poly Character Collection 3 - HDRP.unitypackage.meta
@@ -0,0 +1,15 @@
+fileFormatVersion: 2
+guid: 6236278daa4d5c441a8232dab5ebc22d
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+AssetOrigin:
+ serializedVersion: 1
+ productId: 388758
+ packageName: Low Poly Character Collection 3
+ packageVersion: 1.1
+ assetPath: Assets/Hodaart/HodaartLowPolyCharacterCollection3/Packages/Hodaart Low
+ Poly Character Collection 3 - HDRP.unitypackage
+ uploadId: 946460
diff --git a/Assets/Physics/Bot_LowFriction.physicsMaterial b/Assets/Physics/Bot_LowFriction.physicsMaterial
deleted file mode 100644
index 8f8abf7..0000000
--- a/Assets/Physics/Bot_LowFriction.physicsMaterial
+++ /dev/null
@@ -1,15 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!134 &13400000
-PhysicsMaterial:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_Name: Bot_LowFriction
- serializedVersion: 2
- m_DynamicFriction: 0.3
- m_StaticFriction: 0.3
- m_Bounciness: 0
- m_FrictionCombine: 2
- m_BounceCombine: 2
diff --git a/Assets/Physics/Bot_LowFriction.physicsMaterial.meta b/Assets/Physics/Bot_LowFriction.physicsMaterial.meta
deleted file mode 100644
index 3fc2129..0000000
--- a/Assets/Physics/Bot_LowFriction.physicsMaterial.meta
+++ /dev/null
@@ -1,7 +0,0 @@
-fileFormatVersion: 2
-guid: 6c687d24b6f5fbb4783d28d635f71a29
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
diff --git a/Assets/Scenes/M1_Arena.unity b/Assets/Scenes/M1_Arena.unity
index b25770a..a9f7918 100644
--- a/Assets/Scenes/M1_Arena.unity
+++ b/Assets/Scenes/M1_Arena.unity
@@ -469,118 +469,6 @@ Transform:
m_CorrespondingSourceObject: {fileID: 400000, guid: 463e9d66ec2b7ad428d27c80a2b2d1db, type: 3}
m_PrefabInstance: {fileID: 67875927}
m_PrefabAsset: {fileID: 0}
---- !u!1 &101108170
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 101108171}
- - component: {fileID: 101108174}
- - component: {fileID: 101108173}
- - component: {fileID: 101108172}
- m_Layer: 0
- m_Name: Stand_Platform
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 2147483647
- m_IsActive: 1
---- !u!4 &101108171
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 101108170}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 1.5, z: 0}
- m_LocalScale: {x: 12, y: 3, z: 5}
- m_ConstrainProportionsScale: 0
- m_Children: []
- m_Father: {fileID: 1532509717}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!23 &101108172
-MeshRenderer:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 101108170}
- m_Enabled: 1
- m_CastShadows: 1
- m_ReceiveShadows: 1
- m_DynamicOccludee: 1
- m_StaticShadowCaster: 0
- m_MotionVectors: 1
- m_LightProbeUsage: 1
- m_ReflectionProbeUsage: 1
- m_RayTracingMode: 2
- m_RayTraceProcedural: 0
- m_RayTracingAccelStructBuildFlagsOverride: 0
- m_RayTracingAccelStructBuildFlags: 1
- m_SmallMeshCulling: 1
- m_ForceMeshLod: -1
- m_MeshLodSelectionBias: 0
- m_RenderingLayerMask: 1
- m_RendererPriority: 0
- m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
- m_StaticBatchInfo:
- firstSubMesh: 0
- subMeshCount: 0
- m_StaticBatchRoot: {fileID: 0}
- m_ProbeAnchor: {fileID: 0}
- m_LightProbeVolumeOverride: {fileID: 0}
- m_ScaleInLightmap: 1
- m_ReceiveGI: 1
- m_PreserveUVs: 1
- m_IgnoreNormalsForChartDetection: 0
- m_ImportantGI: 0
- m_StitchLightmapSeams: 1
- m_SelectedEditorRenderState: 3
- m_MinimumChartSize: 4
- m_AutoUVMaxDistance: 0.5
- m_AutoUVMaxAngle: 89
- m_LightmapParameters: {fileID: 0}
- m_GlobalIlluminationMeshLod: 0
- m_SortingLayerID: 0
- m_SortingLayer: 0
- m_SortingOrder: 0
- m_MaskInteraction: 0
- m_AdditionalVertexStreams: {fileID: 0}
---- !u!65 &101108173
-BoxCollider:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 101108170}
- m_Material: {fileID: 0}
- m_IncludeLayers:
- serializedVersion: 2
- m_Bits: 0
- m_ExcludeLayers:
- serializedVersion: 2
- m_Bits: 0
- m_LayerOverridePriority: 0
- m_IsTrigger: 0
- m_ProvidesContacts: 0
- m_Enabled: 1
- serializedVersion: 3
- m_Size: {x: 1, y: 1, z: 1}
- m_Center: {x: 0, y: 0, z: 0}
---- !u!33 &101108174
-MeshFilter:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 101108170}
- m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1001 &130342001
PrefabInstance:
m_ObjectHideFlags: 0
@@ -1484,37 +1372,6 @@ BoxCollider:
serializedVersion: 3
m_Size: {x: 150.5, y: 4, z: 0.5}
m_Center: {x: 0, y: 0, z: 0}
---- !u!1 &506345465
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 506345466}
- m_Layer: 0
- m_Name: StandPoint_1
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &506345466
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 506345465}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: 1, z: 0, w: -0.00000004371139}
- m_LocalPosition: {x: 2.5, y: 3, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_ConstrainProportionsScale: 0
- m_Children: []
- m_Father: {fileID: 1532509717}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &562137767
GameObject:
m_ObjectHideFlags: 0
@@ -1527,7 +1384,6 @@ GameObject:
- component: {fileID: 562137769}
- component: {fileID: 562137768}
- component: {fileID: 562137771}
- - component: {fileID: 562137772}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
@@ -1627,30 +1483,6 @@ MonoBehaviour:
positionSmoothTime: 0.25
lookAtDegreesPerSecond: 180
lookAtHeightOffset: 1
---- !u!114 &562137772
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 562137767}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: cd21368c9a8b1064d913c375fb607c0b, type: 3}
- m_Name:
- m_EditorClassIdentifier: Assembly-CSharp::Jankenbots.Prototype.CameraDirector
- avatarDistance: 8
- robotDistance: 16
- lookSensitivity: 0.18
- zoomSensitivity: 4
- minDistance: 3
- maxDistance: 80
- minPitch: -8
- maxPitch: 78
- lookHeight: 1.2
- orbitRadius: 20
- orbitHeight: 9
- orbitSpeed: 18
--- !u!1001 &579422633
PrefabInstance:
m_ObjectHideFlags: 0
@@ -3447,7 +3279,7 @@ BoxCollider:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 781174154}
- m_Material: {fileID: 13400000, guid: 6c687d24b6f5fbb4783d28d635f71a29, type: 2}
+ m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
@@ -3947,37 +3779,6 @@ Transform:
m_CorrespondingSourceObject: {fileID: 400000, guid: 5161c2c79aa7dc44b8a812f624bf37d7, type: 3}
m_PrefabInstance: {fileID: 893957807}
m_PrefabAsset: {fileID: 0}
---- !u!1 &903945605
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 903945606}
- m_Layer: 0
- m_Name: StandPoint_0
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &903945606
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 903945605}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: 1, z: 0, w: -0.00000004371139}
- m_LocalPosition: {x: -2.5, y: 3, z: 0}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_ConstrainProportionsScale: 0
- m_Children: []
- m_Father: {fileID: 1532509717}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &912005198
PrefabInstance:
m_ObjectHideFlags: 0
@@ -4398,63 +4199,6 @@ Transform:
m_CorrespondingSourceObject: {fileID: 400000, guid: 00ba75879d6ef5745a4888259bde7c0a, type: 3}
m_PrefabInstance: {fileID: 954444310}
m_PrefabAsset: {fileID: 0}
---- !u!1001 &974200701
-PrefabInstance:
- m_ObjectHideFlags: 0
- serializedVersion: 2
- m_Modification:
- serializedVersion: 3
- m_TransformParent: {fileID: 0}
- m_Modifications:
- - target: {fileID: 100000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_Name
- value: Bath
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalPosition.x
- value: 6.622743
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalPosition.y
- value: 0.10000037
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalPosition.z
- value: -0.529232
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalRotation.w
- value: 1
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalRotation.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalRotation.y
- value: -0
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalRotation.z
- value: -0
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalEulerAnglesHint.x
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalEulerAnglesHint.y
- value: 0
- objectReference: {fileID: 0}
- - target: {fileID: 400000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
- propertyPath: m_LocalEulerAnglesHint.z
- value: 0
- objectReference: {fileID: 0}
- m_RemovedComponents: []
- m_RemovedGameObjects: []
- m_AddedGameObjects: []
- m_AddedComponents: []
- m_SourcePrefab: {fileID: 100100000, guid: ae8352c51c6124747aa9e8a7374b86af, type: 3}
--- !u!1001 &974860797
PrefabInstance:
m_ObjectHideFlags: 0
@@ -5627,7 +5371,6 @@ MonoBehaviour:
chassis: {fileID: 0}
cruiseForce: 450
throttleDeadzone: 0.08
- yawAssistTorque: 220
pivotAnchorStrength: 1500
pivotAngularResistance: 400
leanTorque: 500
@@ -5763,7 +5506,6 @@ MonoBehaviour:
chassis: {fileID: 0}
cruiseForce: 450
throttleDeadzone: 0.08
- yawAssistTorque: 220
pivotAnchorStrength: 1500
pivotAngularResistance: 400
leanTorque: 500
@@ -7172,40 +6914,6 @@ Transform:
m_CorrespondingSourceObject: {fileID: 400000, guid: 034ba005b2423b84ebc087e917744363, type: 3}
m_PrefabInstance: {fileID: 1531216050}
m_PrefabAsset: {fileID: 0}
---- !u!1 &1532509716
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1532509717}
- m_Layer: 0
- m_Name: Stand
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!4 &1532509717
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1532509716}
- serializedVersion: 2
- m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
- m_LocalPosition: {x: 0, y: 0, z: 82}
- m_LocalScale: {x: 1, y: 1, z: 1}
- m_ConstrainProportionsScale: 0
- m_Children:
- - {fileID: 101108171}
- - {fileID: 903945606}
- - {fileID: 506345466}
- m_Father: {fileID: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &1537562849
PrefabInstance:
m_ObjectHideFlags: 0
@@ -8752,5 +8460,3 @@ SceneRoots:
- {fileID: 1378796740}
- {fileID: 850707848}
- {fileID: 326006527}
- - {fileID: 1532509717}
- - {fileID: 974200701}
diff --git a/Assets/Scripts/Bot/SeatManager.cs b/Assets/Scripts/Bot/SeatManager.cs
index abc1f88..433ad70 100644
--- a/Assets/Scripts/Bot/SeatManager.cs
+++ b/Assets/Scripts/Bot/SeatManager.cs
@@ -179,20 +179,6 @@ namespace Jankenbots.Prototype
{
ReleaseSeatRpc();
}
-
- // Controls hint under the seat box — context-aware (on foot vs driving).
- int ty = y + h + 6, th = 54;
- GUI.Box(new Rect(x, ty, w, th), "Controls");
- if (mine.HasValue)
- {
- GUI.Label(new Rect(x + 10, ty + 20, w - 20, 18), "W throttle · LShift pivot · A/D lean");
- GUI.Label(new Rect(x + 10, ty + 34, w - 20, 18), "Q leave · V camera · turn: differ vs teammate");
- }
- else
- {
- GUI.Label(new Rect(x + 10, ty + 20, w - 20, 18), "WASD move · Mouse look · Scroll zoom");
- GUI.Label(new Rect(x + 10, ty + 34, w - 20, 18), "E claim tread · V camera · Esc free cursor");
- }
}
static string SeatLabel(ulong pilot) => pilot == NoPilot ? "free" : $"#{pilot}";
diff --git a/Assets/Scripts/Bot/TreadPart.cs b/Assets/Scripts/Bot/TreadPart.cs
index c852ea9..50c6e0d 100644
--- a/Assets/Scripts/Bot/TreadPart.cs
+++ b/Assets/Scripts/Bot/TreadPart.cs
@@ -63,9 +63,6 @@ namespace Jankenbots.Prototype
[Range(0f, 0.5f)]
public float throttleDeadzone = 0.08f;
- [Tooltip("Extra yaw torque (N·m) at full throttle, REINFORCING the natural differential turn so steering reads clearly even with ground friction. Left/Right push opposite ways, so equal throttle cancels to zero → straight line preserved. Set 0 to rely on pure emergent differential. Flip sign in code if it ever fights the turn.")]
- public float yawAssistTorque = 220f;
-
// ---- (b) LOCK-PIVOT tuning -----------------------------------------------
[Header("(b) Lock-pivot — plant this tread as an anchor")]
[Tooltip("How hard the planted tread resists the chassis sliding at its position.")]
@@ -195,13 +192,6 @@ namespace Jankenbots.Prototype
{
Vector3 drive = transform.forward * (_throttle * cruiseForce);
chassis.AddForceAtPosition(drive, treadPos, ForceMode.Force);
-
- // Yaw assist: reinforce the differential turn (Left throttles → nose right,
- // Right throttles → nose left). Cancels to zero when both throttle equally,
- // so straight-line driving is untouched; the maxAngularVelocity clamp still
- // caps total spin so this can't reintroduce an uncontrolled tip.
- float yawSign = side == Side.Left ? 1f : -1f;
- chassis.AddTorque(chassis.transform.up * (yawSign * _throttle * yawAssistTorque), ForceMode.Force);
}
// ---- (c) PASSIVE LEAN — anti-tip ballast ---------------------------
diff --git a/Assets/Scripts/Camera/CameraDirector.cs b/Assets/Scripts/Camera/CameraDirector.cs
deleted file mode 100644
index 770120d..0000000
--- a/Assets/Scripts/Camera/CameraDirector.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-using Unity.Cinemachine;
-using UnityEngine;
-using UnityEngine.InputSystem;
-
-namespace Jankenbots.Prototype
-{
- ///
- /// JANKENBOTS — client-local camera director. Owns four Cinemachine cameras, lets
- /// the local player cycle between them and orbit/zoom the follow cams; the
- /// CinemachineBrain on this Camera blends smoothly on every switch.
- ///
- /// • AvatarFollow — orbitable 3rd-person cam on YOUR character (on-foot).
- /// • RobotFollow — orbitable chase cam on the bot (driving).
- /// • StandView — fixed view from your player stand, looking at the bot.
- /// • CinematicOrbit— slow auto-orbit of the bot (spectate / flavor).
- ///
- /// LOOK / ZOOM (Avatar & Robot only): hold RIGHT MOUSE and drag to orbit
- /// (yaw/pitch), scroll wheel to zoom in/out (out to so
- /// you can pull back and see the arena). RMB-drag keeps the cursor free for the
- /// Claim/Leave buttons until the walk-up interaction exists.
- ///
- /// Default mode auto-follows the control state (on foot → Avatar, seated → Robot),
- /// reading the same seat flag as the control handoff ().
- /// Press V to cycle manually. Cameras are purely client-local, never networked.
- ///
- [RequireComponent(typeof(Camera))]
- public class CameraDirector : MonoBehaviour
- {
- public enum Mode { AvatarFollow, RobotFollow, StandView, CinematicOrbit }
-
- [Header("Follow distances")]
- public float avatarDistance = 8f;
- public float robotDistance = 16f;
-
- [Header("Look / zoom (Avatar & Robot)")]
- [Tooltip("Degrees of orbit per pixel of mouse drag (while holding RMB).")]
- public float lookSensitivity = 0.18f;
- [Tooltip("Metres of zoom per scroll notch.")]
- public float zoomSensitivity = 4f;
- public float minDistance = 3f;
- [Tooltip("How far you can pull the camera back. Big so you can survey the arena.")]
- public float maxDistance = 80f;
- public float minPitch = -8f;
- public float maxPitch = 78f;
- public float lookHeight = 1.2f; // aim a bit above the target pivot
-
- [Header("Cinematic orbit")]
- public float orbitRadius = 22f;
- public float orbitHeight = 10f;
- public float orbitSpeed = 16f; // deg/sec
-
- Transform _bot, _standOverlook;
- CinemachineCamera _avatar, _robot, _stand, _orbit;
- CinemachineCamera[] _all;
- Mode _mode = Mode.AvatarFollow;
- bool _userOverride;
- bool _lastSeated;
-
- // Orbit state shared by the two follow cams (player-controlled).
- float _yaw;
- float _pitch = 18f;
- float _dist = 8f;
- float _cineAngle;
- bool _cursorFree; // Esc toggles the locked cursor free (for GUI / to escape play)
-
- PlayerAvatar _local;
-
- void Start()
- {
- if (GetComponent() == null) gameObject.AddComponent();
- var legacy = GetComponent();
- if (legacy != null) legacy.enabled = false;
-
- var b = GameObject.Find("Bot"); if (b != null) _bot = b.transform;
- var s = GameObject.Find("StandPoint_0"); if (s != null) _standOverlook = s.transform;
-
- var holder = new GameObject("CameraRigs").transform;
- _avatar = Make(holder, "CM_AvatarFollow");
- _robot = Make(holder, "CM_RobotFollow");
- _stand = Make(holder, "CM_StandView");
- _orbit = Make(holder, "CM_CinematicOrbit");
- _all = new[] { _avatar, _robot, _stand, _orbit };
- Apply(_mode);
- }
-
- CinemachineCamera Make(Transform parent, string name)
- {
- var go = new GameObject(name);
- go.transform.SetParent(parent, false);
- var vc = go.AddComponent();
- vc.Priority = 0;
- return vc;
- }
-
- void Update()
- {
- if (_local == null) _local = FindLocal();
-
- var kb = Keyboard.current;
- if (kb != null && kb.vKey.wasPressedThisFrame)
- {
- _mode = (Mode)(((int)_mode + 1) % _all.Length);
- _userOverride = true;
- Apply(_mode);
- }
-
- // Seat claim/leave re-asserts the sensible default (clears a manual override).
- if (_local != null && _local.IsSeatedLocal != _lastSeated)
- {
- _lastSeated = _local.IsSeatedLocal;
- _userOverride = false;
- }
- if (!_userOverride && _local != null)
- {
- Mode want = _local.IsSeatedLocal ? Mode.RobotFollow : Mode.AvatarFollow;
- if (want != _mode) { _mode = want; Apply(_mode); }
- }
-
- // Cursor + look. On-foot (AvatarFollow) uses ALWAYS-ON mouse-look with a
- // locked cursor (no RMB needed); other modes keep the cursor free (RobotFollow
- // orbits while RMB is held). Esc toggles the cursor free to reach GUI / escape.
- if (kb != null && kb.escapeKey.wasPressedThisFrame) _cursorFree = !_cursorFree;
- bool avatarLook = _mode == Mode.AvatarFollow && !_cursorFree;
- Cursor.lockState = avatarLook ? CursorLockMode.Locked : CursorLockMode.None;
- Cursor.visible = !avatarLook;
-
- if (_mode == Mode.AvatarFollow || _mode == Mode.RobotFollow)
- {
- var m = Mouse.current;
- if (m != null)
- {
- bool look = _mode == Mode.AvatarFollow ? avatarLook : m.rightButton.isPressed;
- if (look)
- {
- Vector2 d = m.delta.ReadValue();
- _yaw += d.x * lookSensitivity;
- _pitch = Mathf.Clamp(_pitch - d.y * lookSensitivity, minPitch, maxPitch);
- }
- float scroll = m.scroll.ReadValue().y;
- if (Mathf.Abs(scroll) > 0.01f)
- _dist = Mathf.Clamp(_dist - Mathf.Sign(scroll) * zoomSensitivity, minDistance, maxDistance);
- }
- }
- }
-
- void LateUpdate()
- {
- if (_local != null) PoseOrbit(_avatar, _local.transform);
-
- if (_bot != null)
- {
- PoseOrbit(_robot, _bot);
-
- _cineAngle += orbitSpeed * Time.deltaTime;
- Vector3 focus = _bot.position + Vector3.up * lookHeight;
- Vector3 cineOff = Quaternion.Euler(0f, _cineAngle, 0f) * new Vector3(0f, orbitHeight, -orbitRadius);
- _orbit.transform.position = focus + cineOff;
- _orbit.transform.rotation = Quaternion.LookRotation(focus - _orbit.transform.position);
-
- if (_standOverlook != null)
- {
- _stand.transform.position = _standOverlook.position + Vector3.up * 1.5f;
- _stand.transform.rotation = Quaternion.LookRotation(
- (_bot.position + Vector3.up * lookHeight) - _stand.transform.position);
- }
- }
- }
-
- // Player-controllable orbit: spherical offset from the target driven by _yaw/_pitch/_dist.
- void PoseOrbit(CinemachineCamera vc, Transform target)
- {
- Vector3 focus = target.position + Vector3.up * lookHeight;
- Vector3 dir = Quaternion.Euler(_pitch, _yaw, 0f) * Vector3.back;
- Vector3 pos = focus + dir * _dist;
- vc.transform.position = pos;
- vc.transform.rotation = Quaternion.LookRotation(focus - pos);
- }
-
- PlayerAvatar FindLocal()
- {
- foreach (var a in FindObjectsByType(FindObjectsSortMode.None))
- if (a.IsOwner) return a;
- return null;
- }
-
- void Apply(Mode m)
- {
- for (int i = 0; i < _all.Length; i++)
- _all[i].Priority = ((int)m == i) ? 20 : 0;
-
- // Reset zoom to the mode's default distance on switch (keep the look angle).
- if (m == Mode.AvatarFollow) _dist = avatarDistance;
- else if (m == Mode.RobotFollow) _dist = robotDistance;
- }
- }
-}
diff --git a/Assets/Scripts/Camera/CameraDirector.cs.meta b/Assets/Scripts/Camera/CameraDirector.cs.meta
deleted file mode 100644
index 1e54c67..0000000
--- a/Assets/Scripts/Camera/CameraDirector.cs.meta
+++ /dev/null
@@ -1,2 +0,0 @@
-fileFormatVersion: 2
-guid: cd21368c9a8b1064d913c375fb607c0b
\ No newline at end of file
diff --git a/Assets/Scripts/Player/PlayerAvatar.cs b/Assets/Scripts/Player/PlayerAvatar.cs
index 97a22fa..6c9eaaf 100644
--- a/Assets/Scripts/Player/PlayerAvatar.cs
+++ b/Assets/Scripts/Player/PlayerAvatar.cs
@@ -1,5 +1,4 @@
using Unity.Netcode;
-using Unity.Netcode.Components;
using UnityEngine;
using UnityEngine.InputSystem;
@@ -7,24 +6,25 @@ namespace Jankenbots.Prototype
{
///
/// JANKENBOTS — networked run-around PLAYER avatar (the rigged low-poly
- /// character), PLUS the on-foot ↔ driving control handoff.
+ /// character). This is the foundation for the timed junkyard "gather parts"
+ /// phase: each player controls one of these, runs around, and (later) hauls
+ /// scrap back to build the bot. Driving the finished bot happens from player
+ /// stands, so the avatar and the tread controls are separate systems.
///
- /// CONTROL MODEL (the spine): a player is in exactly one mode, derived from a
- /// single fact — do I currently hold a bot seat? ().
- /// • ON FOOT (no seat) → WASD drives THIS avatar; free-roaming.
- /// • DRIVING (holds a seat)→ avatar TELEPORTS to its player stand and FREEZES;
- /// it refuses all input, so control transfers and
- /// locks to the claimed tread (TreadPart already only
- /// listens when you hold its seat). Release the seat →
- /// teleport back and resume on-foot control.
- /// This is what resolves the WASD overlap: PlayerAvatar and TreadPart become
- /// mutually exclusive off one flag — never both live at once.
+ /// NETCODE: OWNER-authoritative. Only the owning client reads input and moves
+ /// its CharacterController; an on the
+ /// same object replicates the resulting motion to everyone. No host round-trip
+ /// on your own movement → it feels responsive.
///
- /// NETCODE: OWNER-authoritative movement (see ).
- /// Teleports use NetworkTransform.Teleport so observers don't see a slide.
+ /// ANIMATION: derived LOCALLY on every client from the avatar's measured
+ /// horizontal speed (position delta / dt), fed into the Animator's "Speed"
+ /// float, which drives an Idle→Walk→Run 1-D blend tree. Because observers
+ /// measure the same replicated motion the owner produces, the animation stays
+ /// in sync with zero extra network traffic — no NetworkAnimator needed.
///
- /// ANIMATION: derived locally on every client from measured horizontal speed →
- /// Animator "Speed" → Idle/Walk/Run blend (stays in sync with no extra traffic).
+ /// NOTE: reads WASD, same keys as the bot's TreadPart — fine while testing the
+ /// avatar in isolation; the real game separates "running" from "driving" via
+ /// the (future) player-stand flow, so a player is never doing both at once.
///
[RequireComponent(typeof(CharacterController))]
public class PlayerAvatar : NetworkBehaviour
@@ -45,41 +45,28 @@ namespace Jankenbots.Prototype
[Tooltip("Gravity (m/s^2, negative). Keeps the CharacterController grounded.")]
public float gravity = -20f;
+ [Header("Animation")]
+ [Tooltip("Speed value the Animator treats as full-run, for normalising the blend.")]
+ public float runAnimSpeed = 5f;
+
CharacterController _cc;
Animator _anim;
- NetworkTransform _nt;
- SeatManager _seats;
- Transform _standLeft, _standRight; // where each pilot teleports (found by name)
-
float _vy; // vertical velocity (gravity)
Vector3 _horizVel; // smoothed horizontal velocity (ramped, not instant)
Vector3 _lastPos;
float _animSpeed;
-
- bool _seated; // am I (owner) currently piloting a tread?
- Vector3 _returnPos; // where to drop me back when I leave the seat
- bool _hasReturn;
-
static readonly int SpeedHash = Animator.StringToHash("Speed");
- /// True while the LOCAL owner is seated/driving — read by the camera director.
- public bool IsSeatedLocal => _seated;
-
void Awake()
{
_cc = GetComponent();
_anim = GetComponentInChildren();
- _nt = GetComponent();
_lastPos = transform.position;
}
public override void OnNetworkSpawn()
{
_lastPos = transform.position;
- _seats = FindFirstObjectByType();
- var sl = GameObject.Find("StandPoint_0"); if (sl != null) _standLeft = sl.transform;
- var sr = GameObject.Find("StandPoint_1"); if (sr != null) _standRight = sr.transform;
-
// Fan owners out a little so multiple players don't stack on the origin.
if (IsOwner)
{
@@ -93,29 +80,7 @@ namespace Jankenbots.Prototype
{
if (!IsSpawned) return;
- if (IsOwner)
- {
- // Derive mode from seat ownership and handle the transition.
- SeatManager.Seat? seat = LocalSeat();
- bool wantSeated = seat.HasValue;
- if (wantSeated != _seated)
- {
- if (wantSeated) EnterSeated(seat.Value);
- else ExitSeated();
- }
-
- // Claim / leave a tread by KEY. On-foot mouse-look locks the cursor, so
- // the OnGUI Claim/Leave buttons aren't clickable — E claims, Q leaves.
- var kb = Keyboard.current;
- if (_seats != null && kb != null)
- {
- if (!_seated && kb.eKey.wasPressedThisFrame) _seats.ClaimSeatRpc();
- else if (_seated && kb.qKey.wasPressedThisFrame) _seats.ReleaseSeatRpc();
- }
-
- // On foot → drive the avatar. Seated → do nothing (control is on the tread).
- if (!_seated) OwnerMove();
- }
+ if (IsOwner) OwnerMove();
// Animation on EVERY client, from measured horizontal speed.
Vector3 delta = transform.position - _lastPos;
@@ -126,46 +91,6 @@ namespace Jankenbots.Prototype
if (_anim != null) _anim.SetFloat(SpeedHash, _animSpeed);
}
- // Which seat (if any) the local player holds — the single source of truth for mode.
- SeatManager.Seat? LocalSeat()
- {
- if (_seats == null || NetworkManager.Singleton == null) return null;
- ulong me = NetworkManager.Singleton.LocalClientId;
- if (_seats.PilotOf(SeatManager.Seat.Left) == me) return SeatManager.Seat.Left;
- if (_seats.PilotOf(SeatManager.Seat.Right) == me) return SeatManager.Seat.Right;
- return null;
- }
-
- void EnterSeated(SeatManager.Seat seat)
- {
- _seated = true;
- _returnPos = transform.position; // remember where I left the arena
- _hasReturn = true;
- _horizVel = Vector3.zero; _vy = 0f;
-
- Transform sp = seat == SeatManager.Seat.Left ? _standLeft : _standRight;
- if (sp != null) TeleportTo(sp.position, sp.rotation);
- }
-
- void ExitSeated()
- {
- _seated = false;
- _horizVel = Vector3.zero; _vy = 0f;
- if (_hasReturn) TeleportTo(_returnPos + Vector3.up * 0.2f, transform.rotation);
- }
-
- // Interpolation-free teleport (CharacterController must be off to move it directly;
- // NetworkTransform.Teleport keeps observers from seeing a slide across the map).
- void TeleportTo(Vector3 pos, Quaternion rot)
- {
- bool ccWas = _cc.enabled;
- _cc.enabled = false;
- transform.SetPositionAndRotation(pos, rot);
- _cc.enabled = ccWas;
- _lastPos = pos;
- if (_nt != null) _nt.Teleport(pos, rot, transform.localScale);
- }
-
void OwnerMove()
{
var kb = Keyboard.current;
@@ -178,23 +103,12 @@ namespace Jankenbots.Prototype
if (kb.sKey.isPressed || kb.downArrowKey.isPressed) v -= 1f;
}
- // CAMERA-RELATIVE movement: W goes the way the camera (mouse) is looking,
- // not world +Z. Basis is the active game camera flattened onto the ground.
- Vector3 camF = Vector3.forward, camR = Vector3.right;
- var cam = Camera.main;
- if (cam != null)
- {
- camF = Vector3.ProjectOnPlane(cam.transform.forward, Vector3.up);
- if (camF.sqrMagnitude < 1e-4f) camF = Vector3.ProjectOnPlane(cam.transform.up, Vector3.up); // looking straight down
- camF.Normalize();
- camR = Vector3.ProjectOnPlane(cam.transform.right, Vector3.up).normalized;
- }
-
- Vector3 input = camR * h + camF * v;
+ Vector3 input = new Vector3(h, 0f, v);
if (input.sqrMagnitude > 1f) input.Normalize();
Vector3 desired = input * moveSpeed;
- // Ramp velocity toward the target instead of snapping (smooth start/stop).
+ // Ramp velocity toward the target instead of snapping — this is what kills
+ // the "jerky/jarring" feel and lets the anim blend Idle→Walk→Run smoothly.
float rate = input.sqrMagnitude > 0.001f ? acceleration : deceleration;
_horizVel = Vector3.MoveTowards(_horizVel, desired, rate * Time.deltaTime);
@@ -203,6 +117,8 @@ namespace Jankenbots.Prototype
_cc.Move((_horizVel + new Vector3(0f, _vy, 0f)) * Time.deltaTime);
+ // Face the way we're actually moving (uses the smoothed velocity, so turns
+ // ease too rather than snapping on a key change).
if (_horizVel.sqrMagnitude > 0.05f)
{
Quaternion target = Quaternion.LookRotation(new Vector3(_horizVel.x, 0f, _horizVel.z));
diff --git a/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset
index 2b0e035..f005b0b 100644
--- a/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset
+++ b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset
@@ -68,7 +68,22 @@ MonoBehaviour:
- rid: 7808513024541851664
- rid: 7808513024541851665
m_RuntimeSettings:
- m_List: []
+ m_List:
+ - rid: 6852985685364965378
+ - rid: 6852985685364965379
+ - rid: 6852985685364965380
+ - rid: 6852985685364965381
+ - rid: 6852985685364965384
+ - rid: 6852985685364965392
+ - rid: 6852985685364965394
+ - rid: 8712630790384254976
+ - rid: 7808513024541851653
+ - rid: 7808513024541851655
+ - rid: 7808513024541851656
+ - rid: 7808513024541851657
+ - rid: 7808513024541851658
+ - rid: 7808513024541851662
+ - rid: 7808513024541851664
m_AssetVersion: 10
m_ObsoleteDefaultVolumeProfile: {fileID: 0}
m_RenderingLayerNames:
diff --git a/Packages/manifest.json b/Packages/manifest.json
index d4e8afd..8eb26be 100644
--- a/Packages/manifest.json
+++ b/Packages/manifest.json
@@ -2,7 +2,6 @@
"dependencies": {
"com.coplaydev.unity-mcp": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#main",
"com.unity.ai.navigation": "2.0.13",
- "com.unity.cinemachine": "3.1.7",
"com.unity.collab-proxy": "2.12.4",
"com.unity.ide.rider": "3.0.38",
"com.unity.ide.visualstudio": "2.0.26",
diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json
index 67e0777..5639ded 100644
--- a/Packages/packages-lock.json
+++ b/Packages/packages-lock.json
@@ -36,16 +36,6 @@
},
"url": "https://packages.unity.com"
},
- "com.unity.cinemachine": {
- "version": "3.1.7",
- "depth": 0,
- "source": "registry",
- "dependencies": {
- "com.unity.splines": "2.0.0",
- "com.unity.modules.imgui": "1.0.0"
- },
- "url": "https://packages.unity.com"
- },
"com.unity.collab-proxy": {
"version": "2.12.4",
"depth": 0,
@@ -252,13 +242,6 @@
},
"url": "https://packages.unity.com"
},
- "com.unity.settings-manager": {
- "version": "2.1.1",
- "depth": 2,
- "source": "registry",
- "dependencies": {},
- "url": "https://packages.unity.com"
- },
"com.unity.shadergraph": {
"version": "17.5.0",
"depth": 1,
@@ -268,17 +251,6 @@
"com.unity.searcher": "4.9.3"
}
},
- "com.unity.splines": {
- "version": "2.9.0",
- "depth": 1,
- "source": "registry",
- "dependencies": {
- "com.unity.mathematics": "1.2.1",
- "com.unity.modules.imgui": "1.0.0",
- "com.unity.settings-manager": "1.0.3"
- },
- "url": "https://packages.unity.com"
- },
"com.unity.test-framework": {
"version": "1.7.0",
"depth": 0,
diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset
index e54c43c..ecbbda3 100644
--- a/ProjectSettings/ProjectSettings.asset
+++ b/ProjectSettings/ProjectSettings.asset
@@ -148,7 +148,7 @@ PlayerSettings:
loadStoreDebugModeEnabled: 0
visionOSBundleVersion: 1.0
tvOSBundleVersion: 1.0
- bundleVersion: 0.2.0
+ bundleVersion: 0.1.0
preloadedAssets:
- {fileID: -944628639613478452, guid: 052faaac586de48259a63d0c4782560b, type: 3}
metroInputSource: 0
diff --git a/scripts/session-git-check.sh b/scripts/session-git-check.sh
deleted file mode 100644
index 61cbab8..0000000
--- a/scripts/session-git-check.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env bash
-# SessionStart digest: fetch remote, report incoming commits + open Forgejo
-# issues/PRs. Emits a Claude hook JSON blob on stdout (additionalContext) so
-# Claude can surface anything actionable at the top of the session.
-# Always exits 0 and always prints valid JSON — must never block a session.
-
-set -o pipefail
-cd "$(dirname "$0")/.." 2>/dev/null || exit 0
-
-digest=""
-add() { digest+="$1"$'\n'; }
-
-# --- Remote fetch + incoming/outgoing commit comparison ------------------
-if git rev-parse --git-dir >/dev/null 2>&1; then
- git fetch --all --quiet 2>/dev/null
- upstream=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null)
- if [ -n "$upstream" ]; then
- incoming=$(git log --oneline "HEAD..$upstream" 2>/dev/null)
- outgoing=$(git log --oneline "$upstream..HEAD" 2>/dev/null)
- if [ -n "$incoming" ]; then
- add "INCOMING commits on $upstream (you are behind — pull to get them):"
- while IFS= read -r l; do add " $l"; done <<< "$incoming"
- # Flag incoming edits to Unity scene/prefab/asset files — risky to pull
- # while the Editor is open (it may overwrite them or hold a stale copy).
- scenefiles=$(git diff --name-only "HEAD..$upstream" 2>/dev/null | grep -Ei '\.(unity|prefab|asset|mat|controller)$')
- if [ -n "$scenefiles" ]; then
- add " *** WARNING: incoming commits change Unity scene/asset files:"
- while IFS= read -r f; do add " $f"; done <<< "$scenefiles"
- add " *** CLOSE or save the Unity Editor before pulling to avoid clobbering scene state."
- fi
- else
- add "Up to date with $upstream (no incoming commits)."
- fi
- [ -n "$outgoing" ] && add "You have $(wc -l <<< "$outgoing") local commit(s) not yet pushed."
- fi
-fi
-
-# --- Forgejo open issues + PRs -------------------------------------------
-remote_url=$(git remote get-url origin 2>/dev/null)
-if [[ "$remote_url" =~ ^https?://([^/]+)/([^/]+)/([^/.]+) ]]; then
- host="${BASH_REMATCH[1]}"; owner="${BASH_REMATCH[2]}"; repo="${BASH_REMATCH[3]}"
- cred=$(grep -m1 "$host" "$HOME/.git-credentials" 2>/dev/null)
- tok=$(sed -E 's#https?://([^@]+)@.*#\1#' <<< "$cred")
- api="https://$host/api/v1/repos/$owner/$repo/issues"
- parse='import sys,json
-try: d=json.load(sys.stdin)
-except: sys.exit(0)
-for i in d: print(" #%d %s (by %s)"%(i["number"],i["title"],i["user"]["login"]))'
- if [ -n "$tok" ]; then
- issues=$(curl -sf --max-time 8 -u "$tok" "$api?state=open&type=issues" 2>/dev/null | python3 -c "$parse" 2>/dev/null)
- prs=$(curl -sf --max-time 8 -u "$tok" "$api?state=open&type=pulls" 2>/dev/null | python3 -c "$parse" 2>/dev/null)
- if [ -n "$issues" ]; then add "OPEN ISSUES:"; add "$issues"; else add "No open issues."; fi
- if [ -n "$prs" ]; then add "OPEN PULL REQUESTS:"; add "$prs"; else add "No open PRs."; fi
- fi
-fi
-
-# --- Emit hook JSON ------------------------------------------------------
-ctx="[Session start — repo/remote status]
-$digest
-If there are INCOMING commits or any open issues/PRs, briefly tell the user at the start of your first reply. If everything is up to date with no open items, do not mention this."
-
-python3 - "$ctx" <<'PY'
-import json,sys
-print(json.dumps({"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":sys.argv[1]},"suppressOutput":True}))
-PY
-exit 0