improved door grabbing. Sometimes leaves ghost hands.

This commit is contained in:
2025-12-15 21:16:03 +02:00
parent 252e7a2fa6
commit 98526fd582
12 changed files with 546 additions and 152 deletions

View File

@@ -0,0 +1,108 @@
using _PROJECT.NewHandPresence;
using System.Collections.Generic;
using UnityEngine;
public enum GrabbingHand
{
Right,
Left
}
public class DoorHandReplacer : MonoBehaviour
{
public GameObject LeftHand;
public GameObject RightHand;
private GrabbingHand? hand = null; // nullable
private SmartHandPresence currentHand = null;
private bool isGrabbing;
// Tracks all hands currently inside the trigger
private HashSet<SmartHandPresence> handsInTrigger = new HashSet<SmartHandPresence>();
public void ManifestDoorHand()
{
if (currentHand == null || hand == null) return;
isGrabbing = true;
switch (hand.Value)
{
case GrabbingHand.Left:
RightHand.SetActive(false);
LeftHand.SetActive(true);
Debug.Log("Dissapearing hand");
break;
case GrabbingHand.Right:
LeftHand.SetActive(false);
RightHand.SetActive(true);
Debug.Log("Dissapearing hand");
break;
}
}
public void DeManifestDoorHand()
{
isGrabbing = false;
LeftHand.SetActive(false);
RightHand.SetActive(false);
if (currentHand == null) return;
}
private void OnTriggerEnter(Collider other)
{
if (isGrabbing) return;
// IMPORTANT: in case hands have multiple colliders
SmartHandPresence playerHand = other.GetComponentInParent<SmartHandPresence>();
if (playerHand == null) return;
handsInTrigger.Add(playerHand);
currentHand = playerHand;
string name = playerHand.gameObject.name;
if (name.Contains("left", System.StringComparison.OrdinalIgnoreCase))
{
hand = GrabbingHand.Left;
}
else if (name.Contains("right", System.StringComparison.OrdinalIgnoreCase))
{
hand = GrabbingHand.Right;
}
}
private void OnTriggerExit(Collider other)
{
if (isGrabbing) return;
SmartHandPresence playerHand = other.GetComponentInParent<SmartHandPresence>();
if (playerHand == null) return;
handsInTrigger.Remove(playerHand);
// If no hands remain, clear everything
if (handsInTrigger.Count == 0)
{
currentHand = null;
hand = null;
}
else
{
// Pick any remaining hand as current
foreach (var remainingHand in handsInTrigger)
{
currentHand = remainingHand;
string name = remainingHand.gameObject.name;
hand = name.Contains("left", System.StringComparison.OrdinalIgnoreCase)
? GrabbingHand.Left
: GrabbingHand.Right;
break;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac36ec1128f62944a96ea2127166b5cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 52fd38741dd12914a862eb9b5917a6e0
ModelImporter:
serializedVersion: 22200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
rigImportErrors:
rigImportWarnings:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant: