Rework diapason with octo arms

This commit is contained in:
2026-02-19 17:16:54 +01:00
parent ec89813b1b
commit 5b1bdaeb90
48 changed files with 2075 additions and 583 deletions
+104 -11
View File
@@ -27,6 +27,9 @@ public class OctoIkArmsImproved : MonoBehaviour
public OctoIkLimb Arm;
public Vector3 RotationOffset;
public RaycastRig[] Raycasts;
[Header("Equipment System")]
public ArmEquipment Equipment;
[HideInInspector] public Vector3 TargetOriginPos;
[HideInInspector] public Quaternion TargetOriginRot;
@@ -47,6 +50,27 @@ public class OctoIkArmsImproved : MonoBehaviour
PoleOriginPos = Arm.Pole.localPosition;
}
}
if (Equipment != null)
{
Equipment.Initialize();
}
}
public bool IsEnvironmentalIkActive()
{
if (Equipment == null)
return Enabled;
return Enabled && Equipment.State == ArmState.Environmental;
}
public float GetEnvironmentalIkWeight()
{
if (Equipment == null)
return 1f;
return Equipment.IkWeight;
}
}
@@ -148,6 +172,19 @@ public class OctoIkArmsImproved : MonoBehaviour
PerformRaycasts();
FindNearestHits();
UpdateArmPositions();
UpdateEquippedPoses();
}
private void UpdateEquippedPoses()
{
for (int i = 0; i < _arms.Length; i++)
{
ArmRig armRig = _arms[i];
if (armRig.Equipment != null)
{
armRig.Equipment.UpdateEquippedPose();
}
}
}
// Cast all configured raycasts and store results
@@ -157,7 +194,7 @@ public class OctoIkArmsImproved : MonoBehaviour
{
ArmRig armRig = _arms[i];
if (!armRig.Enabled || armRig.Raycasts == null)
if (!armRig.IsEnvironmentalIkActive() || armRig.Raycasts == null)
continue;
for (int u = 0; u < armRig.Raycasts.Length; u++)
@@ -247,24 +284,23 @@ public class OctoIkArmsImproved : MonoBehaviour
{
ArmRig armRig = _arms[i];
if (armRig.Arm == null || armRig.Arm.Target == null) continue;
if (!armRig.IsEnvironmentalIkActive())
continue;
RaycastInfos raycastInfos = _nearestHitRaycasts[i];
// Default to origin position/rotation
Vector3 targetPos = armRig.TargetOriginPos;
Quaternion targetRot = armRig.TargetOriginRot;
bool shouldStick = false;
// Check if we should stick to surface
if (raycastInfos.HasHit && _noHitFrameCount[i] < _settings.StabilityFrames)
{
if (IsValidSurface(raycastInfos, i))
{
// Calculate target position on surface
targetPos = armRig.Arm.Target.parent.InverseTransformPoint(raycastInfos.Position);
// Calculate target rotation aligned to surface
targetRot = Quaternion.LookRotation(
-armRig.Arm.Target.parent.InverseTransformDirection(raycastInfos.Normal),
transform.up
@@ -274,12 +310,10 @@ public class OctoIkArmsImproved : MonoBehaviour
}
}
// Smooth stickiness transition
float targetStickiness = shouldStick ? 1f : 0f;
float stickinessSpeed = shouldStick ? _settings.StickSpeed : _settings.ReleaseSpeed;
_currentStickiness[i] = Mathf.MoveTowards(_currentStickiness[i], targetStickiness, stickinessSpeed * Time.deltaTime);
// Apply distance-based stickiness factor (hysteresis)
float distanceFactor = 0f;
if (shouldStick && raycastInfos.HasHit)
{
@@ -287,17 +321,14 @@ public class OctoIkArmsImproved : MonoBehaviour
distanceFactor = Mathf.Clamp01(distanceFactor);
}
float finalStickiness = _currentStickiness[i] * distanceFactor;
float finalStickiness = _currentStickiness[i] * distanceFactor * armRig.GetEnvironmentalIkWeight();
// Calculate interpolation speeds
float posSpeed = Mathf.Lerp(_settings.ReleaseSpeed, _settings.StickSpeed, finalStickiness);
float rotSpeed = _settings.RotationSpeed * Mathf.Deg2Rad;
// Exponential smoothing for natural movement
float tPos = 1f - Mathf.Exp(-posSpeed * Time.deltaTime);
float tRot = 1f - Mathf.Exp(-rotSpeed * Time.deltaTime);
// Apply smooth interpolation
armRig.Arm.Target.localPosition = Vector3.Lerp(armRig.Arm.Target.localPosition, targetPos, tPos);
armRig.Arm.Target.localRotation = Quaternion.Slerp(armRig.Arm.Target.localRotation, targetRot, tRot);
}
@@ -327,4 +358,66 @@ public class OctoIkArmsImproved : MonoBehaviour
return true;
}
public void EquipObjectOnArm(int armIndex, GameObject objectToEquip, System.Action onComplete = null)
{
if (armIndex < 0 || armIndex >= _arms.Length)
{
Debug.LogError($"[OctoIkArms] Invalid arm index: {armIndex}");
return;
}
ArmRig armRig = _arms[armIndex];
if (armRig.Equipment == null)
{
Debug.LogError($"[OctoIkArms] Arm {armIndex} has no Equipment system configured!");
return;
}
armRig.Equipment.StartTransitionToEquipped(objectToEquip, onComplete);
}
public void UnequipObjectFromArm(int armIndex, System.Action onComplete = null)
{
if (armIndex < 0 || armIndex >= _arms.Length)
{
Debug.LogError($"[OctoIkArms] Invalid arm index: {armIndex}");
return;
}
ArmRig armRig = _arms[armIndex];
if (armRig.Equipment == null)
{
Debug.LogError($"[OctoIkArms] Arm {armIndex} has no Equipment system configured!");
return;
}
armRig.Equipment.StartTransitionToEnvironmental(onComplete);
}
public ArmState GetArmState(int armIndex)
{
if (armIndex < 0 || armIndex >= _arms.Length)
return ArmState.Environmental;
if (_arms[armIndex].Equipment == null)
return ArmState.Environmental;
return _arms[armIndex].Equipment.State;
}
public bool IsArmInEnvironmentalMode(int armIndex)
{
return GetArmState(armIndex) == ArmState.Environmental;
}
public ArmEquipment GetArmEquipment(int armIndex)
{
if (armIndex < 0 || armIndex >= _arms.Length)
return null;
return _arms[armIndex].Equipment;
}
}