Added interaction, hand, rigidbody dragging, picking up hammer

This commit is contained in:
nothke
2024-08-18 13:21:38 +02:00
parent 93ecc95bfa
commit d2c3dff101
76 changed files with 5079 additions and 4 deletions

View File

@@ -0,0 +1,113 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Nothke.Utils
{
public static class BoundsUtils
{
// static list for caching, never deallocates
static List<Collider> colliderCache = new List<Collider>();
public static Bounds GetObjectSpaceColliderBounds(GameObject go, bool includeInactive = false)
{
Transform t = go.transform;
var rootW2L = t.worldToLocalMatrix;
go.GetComponentsInChildren(includeInactive, colliderCache);
if (colliderCache.Count == 0)
{
Debug.LogError("Attempting to get bounds of the object but it has no colliders");
return default;
}
Bounds goBounds = GetBoundsInRootSpace(colliderCache[0]);
for (int i = 1; i < colliderCache.Count; i++)
{
Bounds b = GetBoundsInRootSpace(colliderCache[i]);
goBounds.Encapsulate(b);
}
return goBounds;
Bounds GetBoundsInRootSpace(Collider col)
{
Bounds b = col.GetLocalBounds();
Matrix4x4 l2w = col.transform.localToWorldMatrix;
Matrix4x4 local = rootW2L * l2w;
return TransformBounds(local, b);
}
}
public static Bounds GetLocalBounds(this Collider collider)
{
if (collider is BoxCollider)
{
BoxCollider box = (BoxCollider)collider;
return new Bounds(box.center, box.size);
}
else if (collider is SphereCollider)
{
var center = ((SphereCollider)collider).center;
var radius = ((SphereCollider)collider).radius;
Vector3 size = new Vector3(radius * 2, radius * 2, radius * 2);
return new Bounds(center, size);
}
else if (collider is CapsuleCollider)
{
var capsule = (CapsuleCollider)collider;
var r = capsule.radius;
var h = capsule.height;
Vector3 size;
switch (capsule.direction)
{
case 0: size = new Vector3(h, r * 2, r * 2); break;
case 1: size = new Vector3(r * 2, h, r * 2); break;
case 2: size = new Vector3(r * 2, r * 2, h); break;
default: size = default; break;
}
return new Bounds(capsule.center, size);
}
else if (collider is MeshCollider)
{
return ((MeshCollider)collider).sharedMesh.bounds;
}
Debug.LogError("Attempting to get bounds of an unknown collider type");
return new Bounds();
}
public static Bounds TransformBounds(in Matrix4x4 mat, in Bounds bounds)
{
// Find 8 corners of the bounds
Vector3 p0 = bounds.min;
Vector3 p1 = bounds.max;
Vector3 p2 = new Vector3(p0.x, p0.y, p1.z);
Vector3 p3 = new Vector3(p0.x, p1.y, p0.z);
Vector3 p4 = new Vector3(p1.x, p0.y, p0.z);
Vector3 p5 = new Vector3(p0.x, p1.y, p1.z);
Vector3 p6 = new Vector3(p1.x, p0.y, p1.z);
Vector3 p7 = new Vector3(p1.x, p1.y, p0.z);
Bounds b = new Bounds(mat * p0, Vector3.zero);
b.Encapsulate(mat * p1);
b.Encapsulate(mat * p2);
b.Encapsulate(mat * p3);
b.Encapsulate(mat * p4);
b.Encapsulate(mat * p5);
b.Encapsulate(mat * p6);
b.Encapsulate(mat * p7);
return b;
}
public static void DrawBoundsGizmos(in Bounds bounds)
{
Gizmos.DrawWireCube(bounds.center, bounds.size);
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Nothke.Utils
{
public class HandSway : MonoBehaviour
{
public float springRate = 10;
public float softClampAngle = 30;
Quaternion lastRotation;
void Update()
{
Quaternion target = transform.parent.rotation;
lastRotation = Quaternion.Slerp(lastRotation, target, Time.deltaTime * springRate);
lastRotation = SoftClampRotation(target, lastRotation, softClampAngle);
transform.rotation = lastRotation;
}
public static Quaternion SoftClampRotation(Quaternion origin, Quaternion target, float limitAngleDegrees)
{
float angle = Quaternion.Angle(origin, target);
float softAngle = Mathf.Atan(angle * Mathf.PI / 2 / limitAngleDegrees) / Mathf.PI * 2 * limitAngleDegrees;
return Quaternion.RotateTowards(origin, target, softAngle); // note: uses degrees
}
}
}

View File

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

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
using UnityEngine;
namespace Nothke.Utils
{
public static class ObjectPreviewer
{
struct Node
{
public Matrix4x4 transform;
public Mesh mesh;
public Material[] mats;
}
// Static cache
static List<MeshFilter> meshFiltersBuffer;
static List<Node> nodes;
/// <summary>
/// For performance reasons, the cache never deallocates.
/// So, call this to clear the cache only in the case the memory becomes a problem, such as with previewing objects with gigantic hierarchies.
/// (but even if they're gigantic it's quite unlikely it will be a problem)
/// </summary>
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
public static void ReloadCache()
{
meshFiltersBuffer = new List<MeshFilter>();
nodes = new List<Node>();
}
/// <summary>
/// Assigns object for rendering. Call this only once on preview object change. Pass null to clear the object.
/// </summary>
public static void SetObject(GameObject go)
{
nodes.Clear();
meshFiltersBuffer.Clear();
if (go == null)
return;
Matrix4x4 rootW2L = go.transform.worldToLocalMatrix;
// We need to scale in case the root has non 1,1,1 scale
Matrix4x4 rootScaleMatrix = Matrix4x4.Scale(go.transform.localScale);
go.transform.GetComponentsInChildren(meshFiltersBuffer);
foreach (var mf in meshFiltersBuffer)
{
Mesh mesh = mf.sharedMesh;
var mr = mf.GetComponent<MeshRenderer>();
if (mesh == null)
continue;
// Un-transform by root
Matrix4x4 matrix = rootW2L * mf.transform.localToWorldMatrix * rootScaleMatrix;
Material[] mats = null;
if (mr != null)
mats = mr.sharedMaterials;
nodes.Add(new Node()
{
mesh = mesh,
transform = matrix,
mats = mats,
});
}
}
/// <summary>
/// Renders the preview object set with SetObject(). Call this every frame you want the object to be drawn.
/// </summary>
/// <param name="overrideMaterial">The replacement material that the previews will be drawn with. If not assigned, it will use the original material.</param>
public static void Render(Vector3 position, Quaternion rotation, Vector3 scale, Material overrideMaterial = null, int renderLayer = 0)
{
Matrix4x4 previewTransform = Matrix4x4.TRS(position, rotation, scale);
foreach (var node in nodes)
{
for (int subMeshIndex = 0; subMeshIndex < node.mesh.subMeshCount; subMeshIndex++)
{
var mat = overrideMaterial != null ? overrideMaterial : node.mats[Mathf.Clamp(subMeshIndex, 0, node.mats.Length)];
Graphics.DrawMesh(node.mesh, previewTransform * node.transform, mat, renderLayer, null, subMeshIndex);
}
}
}
}
}

View File

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