Commit bfefbe74 by alsunj

Merge branch 'feat/rogue-enemy' into 'main'

Feat/rogue enemy

See merge request alsunj/loputoo_entities!3
parents 10e58362 4bd89bc6
Showing with 11575 additions and 619 deletions
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SwYamlUnresolvedReferencesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
fileFormatVersion: 2
guid: 8fd8c37e630a3a64e8e2636362ea5048
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 92cec7108f023b74588d2faba8836a4a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 80b77087a57869e4e84989cedb3254a2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 5a924c0fdfd89e741bdc831420a6a596
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 929b1e3f9af32424295367e631b0d137
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Unity.Physics.Custom.EditModeTests")]
fileFormatVersion: 2
guid: 016d8a3094fcbdf44961b10be9ac5c56
timeCreated: 1680116734
\ No newline at end of file
fileFormatVersion: 2
guid: df54d2bd08525d5449ae01cf06c0117f
timeCreated: 1678291379
\ No newline at end of file
using System;
using Unity.Mathematics;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace Unity.Physics.Editor
{
class BeveledBoxBoundsHandle : BoxBoundsHandle
{
public float bevelRadius
{
get => math.min(m_BevelRadius, math.cmin(GetSize()) * 0.5f);
set
{
if (!m_IsDragging)
m_BevelRadius = math.max(0f, value);
}
}
float m_BevelRadius = ConvexHullGenerationParameters.Default.BevelRadius;
bool m_IsDragging = false;
static PhysicsBoundsHandleUtility.Corner[] s_Corners = new PhysicsBoundsHandleUtility.Corner[8];
public new void DrawHandle()
{
int prevHotControl = GUIUtility.hotControl;
if (prevHotControl == 0)
m_IsDragging = false;
base.DrawHandle();
int currHotcontrol = GUIUtility.hotControl;
if (currHotcontrol != prevHotControl)
m_IsDragging = currHotcontrol != 0;
}
protected override void DrawWireframe()
{
if (this.bevelRadius <= 0f)
{
base.DrawWireframe();
return;
}
var cameraPosition = float3.zero;
var cameraForward = new float3 { z = 1f };
if (Camera.current != null)
{
cameraPosition = Camera.current.transform.position;
cameraForward = Camera.current.transform.forward;
}
var bounds = new Bounds(this.center, this.size);
bool isCameraInsideBox = Camera.current != null && bounds.Contains(Handles.inverseMatrix.MultiplyPoint(cameraPosition));
var bevelRadius = this.bevelRadius;
var origin = (float3)this.center;
var size = (float3)this.size;
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, 1f), bevelRadius, 0, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(-1f, 1f, 1f), bevelRadius, 0, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, 1f), bevelRadius, 1, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, -1f, 1f), bevelRadius, 1, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, 1f), bevelRadius, 2, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, -1f), bevelRadius, 2, axes, isCameraInsideBox);
var corner = 0.5f * size - new float3(1f) * bevelRadius;
var axisx = new float3(1f, 0f, 0f);
var axisy = new float3(0f, 1f, 0f);
var axisz = new float3(0f, 0f, 1f);
// Since the geometry is transformed by Handles.matrix during rendering, we transform the camera position
// by the inverse matrix so that the two-shaded wireframe will have the proper orientation.
var invMatrix = Handles.inverseMatrix;
cameraPosition = invMatrix.MultiplyPoint(cameraPosition);
cameraForward = invMatrix.MultiplyVector(cameraForward);
var cameraOrtho = Camera.current == null || Camera.current.orthographic;
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, 1f, -1f), quaternion.LookRotation(-axisz, axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[0]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, 1f, 1f), quaternion.LookRotation(-axisx, axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[1]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, 1f, 1f), quaternion.LookRotation(axisz, axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[2]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, 1f, -1f), quaternion.LookRotation(axisx, axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[3]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, -1f, -1f), quaternion.LookRotation(-axisx, -axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[4]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, -1f, 1f), quaternion.LookRotation(axisz, -axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[5]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, -1f, 1f), quaternion.LookRotation(axisx, -axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[6]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, -1f, -1f), quaternion.LookRotation(-axisz, -axisy), cameraPosition, cameraForward, cameraOrtho, bevelRadius, out s_Corners[7]);
for (int i = 0; i < s_Corners.Length; i++)
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[i], true);
// Draw the horizon edges between the corners
for (int upA = 3, upB = 0; upB < 4; upA = upB, upB++)
{
int dnA = upA + 4;
int dnB = upB + 4;
if (s_Corners[upA].splitAxis[0].z && s_Corners[upB].splitAxis[1].x) Handles.DrawLine(s_Corners[upA].points[0], s_Corners[upB].points[1]);
if (s_Corners[upA].splitAxis[1].z && s_Corners[upB].splitAxis[0].x) Handles.DrawLine(s_Corners[upA].points[1], s_Corners[upB].points[0]);
if (s_Corners[dnA].splitAxis[0].x && s_Corners[dnB].splitAxis[1].z) Handles.DrawLine(s_Corners[dnA].points[0], s_Corners[dnB].points[1]);
if (s_Corners[dnA].splitAxis[1].x && s_Corners[dnB].splitAxis[0].z) Handles.DrawLine(s_Corners[dnA].points[1], s_Corners[dnB].points[0]);
if (s_Corners[dnA].splitAxis[0].y && s_Corners[upA].splitAxis[1].y) Handles.DrawLine(s_Corners[dnA].points[0], s_Corners[upA].points[1]);
if (s_Corners[dnA].splitAxis[1].y && s_Corners[upA].splitAxis[0].y) Handles.DrawLine(s_Corners[dnA].points[1], s_Corners[upA].points[0]);
}
}
}
}
fileFormatVersion: 2
guid: be997ba7f25d7f44b8996dfac81c1a3a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace Unity.Physics.Editor
{
class BeveledCylinderBoundsHandle : PrimitiveBoundsHandle
{
public float bevelRadius
{
get => math.min(m_BevelRadius, math.cmin(GetSize()) * 0.5f);
set
{
if (!m_IsDragging)
m_BevelRadius = math.max(0f, value);
}
}
float m_BevelRadius = ConvexHullGenerationParameters.Default.BevelRadius;
bool m_IsDragging = false;
public float height
{
get => GetSize().z;
set
{
var size = GetSize();
size.z = math.max(0f, value);
SetSize(size);
}
}
public float radius
{
get
{
var size = (float3)GetSize();
var diameter = 0f;
// only consider size values on enabled axes
if (IsAxisEnabled(0)) diameter = math.max(diameter, math.abs(size.x));
else if (IsAxisEnabled(1)) diameter = math.max(diameter, math.abs(size.y));
return diameter * 0.5f;
}
set
{
var size = (float3)GetSize();
size.x = size.y = math.max(0f, value * 2.0f);
SetSize(size);
}
}
public int sideCount
{
get => m_SideCount;
set
{
if (value == m_SideCount)
return;
m_SideCount = value;
Array.Resize(ref m_TopPoints, m_SideCount * 2);
Array.Resize(ref m_BottomPoints, m_SideCount * 2);
Array.Resize(ref m_Corners, m_SideCount * 2);
}
}
int m_SideCount;
PhysicsBoundsHandleUtility.Corner[] m_Corners = Array.Empty<PhysicsBoundsHandleUtility.Corner>();
Vector3[] m_TopPoints = Array.Empty<Vector3>();
Vector3[] m_BottomPoints = Array.Empty<Vector3>();
public new void DrawHandle()
{
int prevHotControl = GUIUtility.hotControl;
if (prevHotControl == 0)
m_IsDragging = false;
base.DrawHandle();
int currHotcontrol = GUIUtility.hotControl;
if (currHotcontrol != prevHotControl)
m_IsDragging = currHotcontrol != 0;
}
protected override void DrawWireframe()
{
using (new Handles.DrawingScope(Handles.matrix))
{
var backfacedColor = PhysicsBoundsHandleUtility.GetStateColor(true);
var frontfacedColor = Handles.color;
bool isCameraInsideBox = false;
var radius = this.radius;
var bevelRadius = this.bevelRadius;
var halfHeight = new float3(0f, 0f, height * 0.5f);
var ctr = (float3)center;
var halfAngleStep = math.PI / m_SideCount;
var angleStep = 2f * halfAngleStep;
const float kHalfPI = (math.PI * 0.5f);
var bottom = ctr + halfHeight + new float3 { z = bevelRadius };
var top = ctr - halfHeight - new float3 { z = bevelRadius };
var tangent = new float3(1, 0, 0);
var binormal = new float3(0, 1, 0);
var topBackFaced = PhysicsBoundsHandleUtility.IsBackfaced(top, -tangent, binormal, axes, isCameraInsideBox);
var bottomBackFaced = PhysicsBoundsHandleUtility.IsBackfaced(bottom, tangent, binormal, axes, isCameraInsideBox);
var cameraCenter = float3.zero;
var cameraForward = new float3 { z = 1f };
if (Camera.current != null)
{
cameraCenter = Camera.current.transform.position;
cameraForward = Camera.current.transform.forward;
}
// Since the geometry is transformed by Handles.matrix during rendering, we transform the camera position
// by the inverse matrix so that the two-shaded wireframe will have the proper orientation.
var invMatrix = Handles.inverseMatrix;
cameraCenter = invMatrix.MultiplyPoint(cameraCenter);
cameraForward = invMatrix.MultiplyVector(cameraForward);
var cameraOrtho = Camera.current != null && Camera.current.orthographic;
var noSides = (radius - bevelRadius) < PhysicsBoundsHandleUtility.kDistanceEpsilon;
var up = new float3(0, 0, -1f);
var t = ((m_SideCount - 2) * angleStep);
var xyAngle0 = new float3(math.cos(t), math.sin(t), 0f);
t = (m_SideCount - 1) * angleStep;
var xyAngle1 = new float3(math.cos(t), math.sin(t), 0f);
var sideways1 = new float3(math.cos(t + kHalfPI - halfAngleStep), math.sin(t + kHalfPI - halfAngleStep), 0f);
var direction1 = new float3(math.cos(t + halfAngleStep), math.sin(t + halfAngleStep), 0f);
var bevelGreaterThanZero = bevelRadius > 0f;
var bevelLessThanCylinderRadius = bevelRadius < radius;
for (var i = 0; i < m_SideCount; ++i)
{
t = i * angleStep;
var xyAngle2 = new float3(math.cos(t), math.sin(t), 0f);
var sideways2 = new float3(math.cos(t + kHalfPI - halfAngleStep), math.sin(t + kHalfPI - halfAngleStep), 0f);
var direction2 = new float3(math.cos(t + halfAngleStep), math.sin(t + halfAngleStep), 0f);
var offset0 = xyAngle0 * (radius - bevelRadius);
var offset1 = xyAngle1 * (radius - bevelRadius);
var offset2 = xyAngle2 * (radius - bevelRadius);
var top1 = ctr + offset1 - (halfHeight - new float3 { z = bevelRadius });
var bottom1 = ctr + offset1 + (halfHeight - new float3 { z = bevelRadius });
var top2 = ctr + offset2 - (halfHeight - new float3 { z = bevelRadius });
var bottom2 = ctr + offset2 + (halfHeight - new float3 { z = bevelRadius });
var startOffset = direction1 * bevelRadius;
if (bevelGreaterThanZero)
{
var upOffset = up * bevelRadius;
// top/bottom caps
if (bevelLessThanCylinderRadius)
{
Handles.color = topBackFaced ? backfacedColor : frontfacedColor;
Handles.DrawLine(top1 + upOffset, top2 + upOffset);
Handles.color = bottomBackFaced ? backfacedColor : frontfacedColor;
Handles.DrawLine(bottom1 - upOffset, bottom2 - upOffset);
}
var currSideMidPoint = ctr + ((top1 + bottom1 + top2 + bottom2) * 0.25f) + startOffset;
var currSideBackFaced = PhysicsBoundsHandleUtility.IsBackfaced(currSideMidPoint, up, sideways2, axes, isCameraInsideBox);
Handles.color = currSideBackFaced ? backfacedColor : frontfacedColor;
if (!noSides)
{
// Square side of bevelled cylinder
Handles.DrawLine(top2 + startOffset, bottom2 + startOffset);
Handles.DrawLine(bottom2 + startOffset, bottom1 + startOffset);
Handles.DrawLine(bottom1 + startOffset, top1 + startOffset);
Handles.DrawLine(top1 + startOffset, top2 + startOffset);
}
else
{
// Square side of bevelled cylinder, when squashed to a single line
Handles.DrawLine(top2 + startOffset, bottom2 + startOffset);
}
}
else
{
var top0 = ctr + offset0 - (halfHeight - new float3 { z = bevelRadius });
var bottom0 = ctr + offset0 + (halfHeight - new float3 { z = bevelRadius });
var prevMidPoint = ctr + ((top0 + top1 + bottom0 + bottom1) * 0.25f) + startOffset;
var prevSideBackFaced = PhysicsBoundsHandleUtility.IsBackfaced(prevMidPoint, up, sideways1, axes, isCameraInsideBox);
var currMidPoint = ctr + ((top1 + top2 + bottom1 + bottom2) * 0.25f) + startOffset;
var currSideBackFaced = PhysicsBoundsHandleUtility.IsBackfaced(currMidPoint, up, sideways2, axes, isCameraInsideBox);
// Square side of bevelled cylinder
Handles.color = (currSideBackFaced && prevSideBackFaced) ? backfacedColor : frontfacedColor;
Handles.DrawLine(bottom1 + startOffset, top1 + startOffset);
Handles.color = (currSideBackFaced && topBackFaced) ? backfacedColor : frontfacedColor;
Handles.DrawLine(top1 + startOffset, top2 + startOffset);
Handles.color = (currSideBackFaced && bottomBackFaced) ? backfacedColor : frontfacedColor;
Handles.DrawLine(bottom2 + startOffset, bottom1 + startOffset);
}
if (bevelGreaterThanZero)
{
Handles.color = frontfacedColor;
var cornerIndex0 = i;
var cornerIndex1 = i + m_SideCount;
{
var orientation = quaternion.LookRotation(xyAngle2, up);
var cornerNormal = math.normalize(math.mul(orientation, new float3(0f, 1f, 1f)));
PhysicsBoundsHandleUtility.CalculateCornerHorizon(top2,
new float3x3(direction1, up, direction2),
cornerNormal, cameraCenter, cameraForward, cameraOrtho,
bevelRadius, out m_Corners[cornerIndex0]);
}
{
var orientation = quaternion.LookRotation(xyAngle2, -up);
var cornerNormal = math.normalize(math.mul(orientation, new float3(0f, 1f, 1f)));
PhysicsBoundsHandleUtility.CalculateCornerHorizon(bottom2,
new float3x3(direction2, -up, direction1),
cornerNormal, cameraCenter, cameraForward, cameraOrtho,
bevelRadius, out m_Corners[cornerIndex1]);
}
}
direction1 = direction2;
sideways1 = sideways2;
xyAngle0 = xyAngle1;
xyAngle1 = xyAngle2;
}
if (bevelGreaterThanZero)
{
Handles.color = frontfacedColor;
for (int a = m_SideCount - 1, b = 0; b < m_SideCount; a = b, ++b)
{
var up0 = a;
var dn0 = a + m_SideCount;
var up1 = b;
var dn1 = b + m_SideCount;
// Side horizon on vertical curved edge
if (m_Corners[up1].splitCount > 1 &&
m_Corners[dn1].splitCount > 1)
{
if ((m_Corners[up1].splitAxis[0].y || m_Corners[up1].splitAxis[1].y) &&
(m_Corners[dn1].splitAxis[0].y || m_Corners[dn1].splitAxis[1].y))
{
var point0 = m_Corners[up1].splitAxis[0].y ? m_Corners[up1].points[0] : m_Corners[up1].points[1];
var point1 = m_Corners[dn1].splitAxis[0].y ? m_Corners[dn1].points[0] : m_Corners[dn1].points[1];
Handles.DrawLine(point0, point1);
}
}
// Top horizon on horizontal curved edge
if (m_Corners[up0].splitCount > 1 &&
m_Corners[up1].splitCount > 1)
{
if ((m_Corners[up0].splitAxis[0].x || m_Corners[up0].splitAxis[1].x) &&
(m_Corners[up1].splitAxis[0].z || m_Corners[up1].splitAxis[1].z))
{
var point0 = m_Corners[up0].splitAxis[0].x ? m_Corners[up0].points[0] : m_Corners[up0].points[1];
var point1 = m_Corners[up1].splitAxis[0].z ? m_Corners[up1].points[0] : m_Corners[up1].points[1];
Handles.DrawLine(point0, point1);
}
}
// Bottom horizon on horizontal curved edge
if (m_Corners[dn0].splitCount > 1 &&
m_Corners[dn1].splitCount > 1)
{
if ((m_Corners[dn0].splitAxis[0].z || m_Corners[dn0].splitAxis[1].z) &&
(m_Corners[dn1].splitAxis[0].x || m_Corners[dn1].splitAxis[1].x))
{
var point0 = m_Corners[dn0].splitAxis[0].z ? m_Corners[dn0].points[0] : m_Corners[dn0].points[1];
var point1 = m_Corners[dn1].splitAxis[0].x ? m_Corners[dn1].points[0] : m_Corners[dn1].points[1];
Handles.DrawLine(point0, point1);
}
}
}
for (var i = 0; i < m_Corners.Length; ++i)
PhysicsBoundsHandleUtility.DrawCorner(m_Corners[i], new bool3(true, true, !noSides));
}
}
}
protected override Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds)
{
const int k_DirectionX = 0;
const int k_DirectionY = 1;
const int k_DirectionZ = 2;
var changedAxis = k_DirectionX;
var otherRadiusAxis = k_DirectionY;
switch (handle)
{
case HandleDirection.NegativeY:
case HandleDirection.PositiveY:
changedAxis = k_DirectionY;
otherRadiusAxis = k_DirectionX;
break;
case HandleDirection.NegativeZ:
case HandleDirection.PositiveZ:
changedAxis = k_DirectionZ;
break;
}
var upperBound = newBounds.max;
var lowerBound = newBounds.min;
var convexDiameter = 2f * bevelRadius;
// ensure changed dimension cannot be made less than convex diameter
if (upperBound[changedAxis] - lowerBound[changedAxis] < convexDiameter)
{
switch (handle)
{
case HandleDirection.PositiveX:
case HandleDirection.PositiveY:
case HandleDirection.PositiveZ:
upperBound[changedAxis] = lowerBound[changedAxis] + convexDiameter;
break;
default:
lowerBound[changedAxis] = upperBound[changedAxis] - convexDiameter;
break;
}
}
// ensure radius changes uniformly
if (changedAxis != k_DirectionZ)
{
var rad = 0.5f * (upperBound[changedAxis] - lowerBound[changedAxis]);
lowerBound[otherRadiusAxis] = center[otherRadiusAxis] - rad;
upperBound[otherRadiusAxis] = center[otherRadiusAxis] + rad;
}
return new Bounds((upperBound + lowerBound) * 0.5f, upperBound - lowerBound);
}
}
}
fileFormatVersion: 2
guid: 4f5e502486013d44c9cc7466f6c3bcd1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using static UnityEditor.IMGUI.Controls.PrimitiveBoundsHandle;
namespace Unity.Physics.Editor
{
static class PhysicsBoundsHandleUtility
{
internal const float kBackfaceAlphaMultiplier = 0.2f;
const float kDegreeEpsilon = 0.001f;
public const float kDistanceEpsilon = 0.0001f;
public static bool IsBackfaced(float3 localPos, float3 localTangent, float3 localBinormal, Axes axes, bool isCameraInsideBox)
{
// if inside the box then ignore back facing alpha multiplier (otherwise all handles will look disabled)
if (isCameraInsideBox || axes != Axes.All)
return false;
// use tangent and binormal to calculate normal in case handle matrix is skewed
float3 worldTangent = math.normalize(Handles.matrix.MultiplyVector(localTangent));
float3 worldBinormal = math.normalize(Handles.matrix.MultiplyVector(localBinormal));
float3 worldDir = math.normalize(math.cross(worldTangent, worldBinormal));
// adjust color if handle is back facing
float cosV;
var currentCamera = Camera.current;
if (currentCamera != null && !currentCamera.orthographic)
{
float3 cameraPos = currentCamera.transform.position;
float3 worldPos = Handles.matrix.MultiplyPoint(localPos);
cosV = math.dot(math.normalize(cameraPos - worldPos), worldDir);
}
else
{
float3 cameraForward = currentCamera == null ? Vector3.forward : currentCamera.transform.forward;
cosV = math.dot(-cameraForward, worldDir);
}
return cosV < -0.0001f;
}
public static Color GetStateColor(bool isBackfaced)
{
float alphaMultiplier = isBackfaced ? kBackfaceAlphaMultiplier : 1f;
return Handles.color * new Color(1f, 1f, 1f, alphaMultiplier);
}
static void AdjustMidpointHandleColor(bool isBackfaced)
{
Handles.color = GetStateColor(isBackfaced);
}
static readonly Vector3[] s_FacePoints = new Vector3[8];
static readonly Vector3[] s_LinePoints = new Vector3[2];
static readonly int[] k_NextAxis = { 1, 2, 0 };
public static void DrawFace(float3 center, float3 size, float cornerRadius, int normalAxis, Axes axes, bool isCameraInsideBox)
{
// 0 = 0 1 2
// 1 = 1 2 0
// 2 = 2 0 1
int a = normalAxis;
int b = k_NextAxis[a];
int c = k_NextAxis[b];
cornerRadius = math.abs(cornerRadius);
size *= 0.5f;
var normal = new float3 { [a] = size[a] };
var ctr = center + normal;
size -= new float3(cornerRadius);
// check if our face is a point
if (math.abs(size[c]) < kDistanceEpsilon &&
math.abs(size[b]) < kDistanceEpsilon)
return;
Vector3[] points;
// check if our face is a line or not
if (math.abs(size[c]) >= kDistanceEpsilon &&
math.abs(size[b]) >= kDistanceEpsilon)
{
var i = 0;
s_FacePoints[i++] = ctr + new float3 { [b] = size[b], [c] = size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = -size[b], [c] = size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = -size[b], [c] = size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = -size[b], [c] = -size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = -size[b], [c] = -size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = size[b], [c] = -size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = size[b], [c] = -size[c] };
s_FacePoints[i++] = ctr + new float3 { [b] = size[b], [c] = size[c] };
points = s_FacePoints;
}
else if (math.abs(size[c]) >= kDistanceEpsilon)
{
var i = 0;
s_LinePoints[i++] = ctr + new float3 { [b] = size[b], [c] = size[c] };
s_LinePoints[i++] = ctr + new float3 { [b] = size[b], [c] = -size[c] };
points = s_LinePoints;
}
else
{
var i = 0;
s_LinePoints[i++] = ctr + new float3 { [c] = size[c], [b] = size[b] };
s_LinePoints[i++] = ctr + new float3 { [c] = size[c], [b] = -size[b] };
points = s_LinePoints;
}
float3 tangent, biNormal;
if (size[c] > 0)
{
tangent = math.cross(normal, math.normalizesafe(new float3 { [c] = size[c] }));
biNormal = math.cross(normal, tangent);
}
else
{
tangent = math.cross(normal, math.normalizesafe(new float3 { [b] = size[b] }));
biNormal = math.cross(normal, tangent);
}
using (new Handles.DrawingScope(Handles.color))
{
AdjustMidpointHandleColor(IsBackfaced(ctr, tangent, biNormal, axes, isCameraInsideBox));
Handles.DrawLines(points);
}
}
public struct Corner
{
public float3 angle;
public float3x2 intersections;
public float3x2 points;
public float3x3 axes;
public float3x3 normals;
public bool3x2 splitAxis;
public int splitCount;
public float3 position;
public float radius;
public bool isBackFaced;
public float3 cameraForward;
}
public static void CalculateCornerHorizon(float3 cornerPosition, quaternion orientation, float3 cameraCenter, float3 cameraForward, bool cameraOrtho, float radius, out Corner corner)
{
var axisx = new float3(1f, 0f, 0f);
var axisy = new float3(0f, 1f, 0f);
var axisz = new float3(0f, 0f, 1f);
// a vector pointing away from the center of the corner
var cornerNormal = math.normalize(math.mul(orientation, new float3(1f, 1f, 1f)));
var axes = math.mul(new float3x3(orientation), new float3x3(axisx, axisy, axisz));
CalculateCornerHorizon(cornerPosition,
axes,
cornerNormal,
cameraCenter, cameraForward, cameraOrtho,
radius, out corner);
}
public static void CalculateCornerHorizon(float3 cornerPosition, float3x3 axes, float3 cornerNormal, float3 cameraCenter, float3 cameraForward, bool cameraOrtho, float radius, out Corner corner)
{
var cameraToCenter = cornerPosition - cameraCenter; // vector from camera to center
var sqrRadius = radius * radius;
var sqrDistCameraToCenter = math.lengthsq(cameraToCenter);
var sqrOffset = (sqrRadius * sqrRadius / sqrDistCameraToCenter); // squared distance from actual center to drawn disc center
if (!cameraOrtho)
cameraForward = cameraToCenter;
var normals = new float3x3
{
c0 = math.normalize(math.cross(axes[1], axes[2])),
c1 = math.normalize(math.cross(axes[2], axes[0])),
c2 = math.normalize(math.cross(axes[0], axes[1]))
};
corner = new Corner
{
angle = new float3(
Vector3.Angle(axes[0], axes[1]),
Vector3.Angle(axes[1], axes[2]),
Vector3.Angle(axes[2], axes[0])
),
intersections = default,
points = default,
splitAxis = default,
axes = axes,
normals = normals,
position = cornerPosition,
radius = radius,
cameraForward = cameraForward,
isBackFaced = math.dot(cornerNormal, cameraForward) > 0,
splitCount = 0
};
if (math.abs(sqrDistCameraToCenter) <= sqrRadius)
return;
for (int n = 0, sign = -1; n < 2; n++, sign += 2)
{
for (int i = 0; i < 3; i++)
{
var axis1 = normals[i] * sign;
var axis2 = axes[(i + 1) % 3] * sign;
var axis3 = axes[(i + 2) % 3] * sign;
var Q = Vector3.Angle(cameraForward, axis1);
var f = math.tan(math.radians(90 - math.min(Q, 180 - Q)));
var g = sqrOffset + f * f * sqrOffset;
if (g >= sqrRadius)
continue;
var e = math.degrees(math.asin(math.sqrt(g) / radius));
var vectorToPointOnHorizon = Quaternion.AngleAxis(e, axis1) * math.normalize(math.cross(axis1, cameraForward));
vectorToPointOnHorizon = math.normalize(Vector3.ProjectOnPlane(vectorToPointOnHorizon, axis1));
var intersectionDirection = vectorToPointOnHorizon;
var angle1 = Vector3.SignedAngle(axis2, intersectionDirection, axis1);
var angle2 = Vector3.SignedAngle(axis3, intersectionDirection, axis1);
if (angle1 <= 0 || angle2 >= 0)
continue;
var point = corner.position + (float3)(intersectionDirection * radius);
if (corner.splitCount < 2)
{
corner.splitAxis[corner.splitCount][i] = true;
corner.intersections[corner.splitCount] = intersectionDirection;
corner.points[corner.splitCount] = point;
corner.splitCount++;
}
}
}
if (!math.any(corner.splitAxis[0]) &&
!math.any(corner.splitAxis[1]))
{
corner.splitCount = 0;
corner.splitAxis[0] = false;
corner.splitAxis[1] = false;
}
}
public static void DrawCorner(Corner corner, bool3 showAxis)
{
var color = Handles.color;
var axes = corner.axes;
var intersections = corner.intersections;
var normals = corner.normals;
var origin = corner.position;
var radius = corner.radius;
if (corner.splitCount <= 1)
{
AdjustMidpointHandleColor(corner.isBackFaced);
if (showAxis[0]) Handles.DrawWireArc(origin, normals[0], axes[1], corner.angle[1], radius);
if (showAxis[1]) Handles.DrawWireArc(origin, normals[1], axes[2], corner.angle[2], radius);
if (showAxis[2]) Handles.DrawWireArc(origin, normals[2], axes[0], corner.angle[0], radius);
}
else
{
var angleLength = Vector3.SignedAngle(Vector3.ProjectOnPlane(intersections[0], corner.cameraForward),
Vector3.ProjectOnPlane(intersections[1], corner.cameraForward), corner.cameraForward);
bool reversePolarity = angleLength < 0;
if (reversePolarity)
Handles.DrawWireArc(origin, corner.cameraForward, corner.points[1] - origin, -angleLength, radius);
else
Handles.DrawWireArc(origin, corner.cameraForward, corner.points[0] - origin, angleLength, radius);
var backfacedColor = GetStateColor(true);
var axesBackfaced = new bool3(math.length(intersections[0] - axes[0]) < kDistanceEpsilon || math.length(intersections[1] - axes[0]) < kDistanceEpsilon,
math.length(intersections[0] - axes[1]) < kDistanceEpsilon || math.length(intersections[1] - axes[1]) < kDistanceEpsilon,
math.length(intersections[0] - axes[2]) < kDistanceEpsilon || math.length(intersections[1] - axes[2]) < kDistanceEpsilon);
var color1 = reversePolarity ? color : backfacedColor;
var color2 = reversePolarity ? backfacedColor : color;
for (int A = 1, B = 2, C = 0; C < 3; A = B, B = C, C++)
{
if (corner.splitAxis[0][C] == corner.splitAxis[1][C])
{
if (!axesBackfaced[A]) { angleLength = Vector3.Angle(intersections[0], axes[A]); axesBackfaced[A] = (angleLength<kDegreeEpsilon || angleLength> corner.angle[C] - kDegreeEpsilon); }
if (!axesBackfaced[B]) { angleLength = Vector3.Angle(intersections[1], axes[A]); axesBackfaced[B] = (angleLength<kDegreeEpsilon || angleLength> corner.angle[C] - kDegreeEpsilon); }
}
else if (corner.splitAxis[0][C])
{
if (showAxis[C])
{
angleLength = Vector3.Angle(intersections[0], axes[A]);
Handles.color = color1; Handles.DrawWireArc(origin, normals[C], intersections[0], -angleLength, radius);
Handles.color = color2; Handles.DrawWireArc(origin, normals[C], intersections[0], corner.angle[A] - angleLength, radius);
}
axesBackfaced[A] = true;
}
else
//if (corner.splitAxis[1][C])
{
if (showAxis[C])
{
angleLength = Vector3.Angle(intersections[1], axes[A]);
Handles.color = color2; Handles.DrawWireArc(origin, normals[C], intersections[1], -angleLength, radius);
Handles.color = color1; Handles.DrawWireArc(origin, normals[C], intersections[1], corner.angle[A] - angleLength, radius);
}
axesBackfaced[B] = true;
}
}
// check for singularity
if (math.all(axesBackfaced))
axesBackfaced = corner.isBackFaced;
for (int A = 1, B = 2, C = 0; C < 3; A = B, B = C, C++)
{
if (!showAxis[C])
continue;
if (corner.splitAxis[0][C] == corner.splitAxis[1][C])
{
Handles.color = (axesBackfaced[B] && axesBackfaced[A]) ? color1 : color2;
Handles.DrawWireArc(origin, normals[C], axes[A], corner.angle[A], radius);
}
}
}
Handles.color = color;
}
}
}
fileFormatVersion: 2
guid: e3c60d0e0940c3c419ec030b9685c622
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace Unity.Physics.Editor
{
class PhysicsCapsuleBoundsHandle : CapsuleBoundsHandle
{
static PhysicsBoundsHandleUtility.Corner[] s_Corners = new PhysicsBoundsHandleUtility.Corner[8];
protected override void DrawWireframe()
{
if (this.radius <= 0f)
{
base.DrawWireframe();
return;
}
var cameraPos = default(float3);
var cameraFwd = new float3 { z = 1f };
var cameraOrtho = true;
if (Camera.current != null)
{
cameraPos = Camera.current.transform.position;
cameraFwd = Camera.current.transform.forward;
cameraOrtho = Camera.current.orthographic;
}
var size = new float3(this.radius * 2f, this.radius * 2f, height);
var radius = this.radius;
var origin = (float3)this.center;
var bounds = new Bounds(this.center, size);
// Since the geometry is transformed by Handles.matrix during rendering, we transform the camera position
// by the inverse matrix so that the two-shaded wireframe will have the proper orientation.
var invMatrix = Handles.inverseMatrix;
var cameraCenter = (float3)invMatrix.MultiplyPoint(cameraPos);
var cameraForward = (float3)invMatrix.MultiplyVector(cameraFwd);
bool isCameraInsideBox = Camera.current != null
&& bounds.Contains(invMatrix.MultiplyPoint(cameraPos));
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, 1f), radius, 0, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(-1f, 1f, 1f), radius, 0, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, 1f), radius, 1, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, -1f, 1f), radius, 1, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, 1f), radius, 2, axes, isCameraInsideBox);
PhysicsBoundsHandleUtility.DrawFace(origin, size * new float3(1f, 1f, -1f), radius, 2, axes, isCameraInsideBox);
var corner = 0.5f * size - new float3(1f) * radius;
var axisx = new float3(1f, 0f, 0f);
var axisy = new float3(0f, 1f, 0f);
var axisz = new float3(0f, 0f, 1f);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, 1f, -1f), quaternion.LookRotation(-axisz, axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[0]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, 1f, 1f), quaternion.LookRotation(-axisx, axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[1]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, 1f, 1f), quaternion.LookRotation(axisz, axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[2]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, 1f, -1f), quaternion.LookRotation(axisx, axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[3]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, -1f, -1f), quaternion.LookRotation(-axisx, -axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[4]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(-1f, -1f, 1f), quaternion.LookRotation(axisz, -axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[5]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, -1f, 1f), quaternion.LookRotation(axisx, -axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[6]);
PhysicsBoundsHandleUtility.CalculateCornerHorizon(origin + corner * new float3(1f, -1f, -1f), quaternion.LookRotation(-axisz, -axisy), cameraCenter, cameraForward, cameraOrtho, radius, out s_Corners[7]);
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[0], new bool3(false, true, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[3], new bool3(true, false, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[4], new bool3(true, false, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[7], new bool3(false, true, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[1], new bool3(true, false, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[2], new bool3(false, true, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[5], new bool3(false, true, true));
PhysicsBoundsHandleUtility.DrawCorner(s_Corners[6], new bool3(true, false, true));
// Draw the horizon edges between the corners
for (int upA = 3, upB = 0; upB < 4; upA = upB, upB++)
{
int dnA = upA + 4;
int dnB = upB + 4;
if (s_Corners[upA].splitAxis[0].z && s_Corners[upB].splitAxis[1].x) Handles.DrawLine(s_Corners[upA].points[0], s_Corners[upB].points[1]);
if (s_Corners[upA].splitAxis[1].z && s_Corners[upB].splitAxis[0].x) Handles.DrawLine(s_Corners[upA].points[1], s_Corners[upB].points[0]);
if (s_Corners[dnA].splitAxis[0].x && s_Corners[dnB].splitAxis[1].z) Handles.DrawLine(s_Corners[dnA].points[0], s_Corners[dnB].points[1]);
if (s_Corners[dnA].splitAxis[1].x && s_Corners[dnB].splitAxis[0].z) Handles.DrawLine(s_Corners[dnA].points[1], s_Corners[dnB].points[0]);
if (s_Corners[dnA].splitAxis[0].y && s_Corners[upA].splitAxis[1].y) Handles.DrawLine(s_Corners[dnA].points[0], s_Corners[upA].points[1]);
if (s_Corners[dnA].splitAxis[1].y && s_Corners[upA].splitAxis[0].y) Handles.DrawLine(s_Corners[dnA].points[1], s_Corners[upA].points[0]);
}
}
}
}
fileFormatVersion: 2
guid: c1af170fae6badc40bb2ed5376031c6f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace Unity.Physics.Editor
{
class PhysicsSphereBoundsHandle : SphereBoundsHandle
{
protected override void DrawWireframe()
{
bool x = IsAxisEnabled(Axes.X);
bool y = IsAxisEnabled(Axes.Y);
bool z = IsAxisEnabled(Axes.Z);
if (x && !y && !z)
Handles.DrawLine(Vector3.right * radius, Vector3.left * radius);
if (!x && y && !z)
Handles.DrawLine(Vector3.up * radius, Vector3.down * radius);
if (!x && !y && z)
Handles.DrawLine(Vector3.forward * radius, Vector3.back * radius);
const float kEpsilon = 0.000001F;
if (radius > 0)
{
var frontfacedColor = Handles.color;
var backfacedColor = Handles.color * new Color(1f, 1f, 1f, PhysicsBoundsHandleUtility.kBackfaceAlphaMultiplier);
var discVisible = new bool[]
{
y && z,
x && z,
x && y
};
var discOrientations = new float3[]
{
Vector3.right,
Vector3.up,
Vector3.forward
};
// Since the geometry is transformed by Handles.matrix during rendering, we transform the camera position
// by the inverse matrix so that the two-shaded wireframe will have the proper orientation.
var invMatrix = Handles.inverseMatrix;
var cameraCenter = Camera.current == null ? Vector3.zero : Camera.current.transform.position;
var cameraToCenter = center - invMatrix.MultiplyPoint(cameraCenter); // vector from camera to center
var sqrDistCameraToCenter = cameraToCenter.sqrMagnitude;
var sqrRadius = radius * radius; // squared radius
var isCameraOrthographic = Camera.current == null || Camera.current.orthographic;
var sqrOffset = isCameraOrthographic ? 0 : (sqrRadius * sqrRadius / sqrDistCameraToCenter); // squared distance from actual center to drawn disc center
var insideAmount = sqrOffset / sqrRadius;
if (insideAmount < 1)
{
if (math.abs(sqrDistCameraToCenter) >= kEpsilon)
{
using (new Handles.DrawingScope(frontfacedColor))
{
if (isCameraOrthographic)
{
var horizonRadius = radius;
var horizonCenter = center;
Handles.DrawWireDisc(horizonCenter, cameraToCenter, horizonRadius);
}
else
{
var horizonRadius = math.sqrt(sqrRadius - sqrOffset);
var horizonCenter = center - sqrRadius * cameraToCenter / sqrDistCameraToCenter;
Handles.DrawWireDisc(horizonCenter, cameraToCenter, horizonRadius);
}
}
var planeNormal = cameraToCenter.normalized;
for (int i = 0; i < 3; i++)
{
if (!discVisible[i])
continue;
var discOrientation = discOrientations[i];
var angleBetweenDiscAndNormal = math.acos(math.dot(discOrientation, planeNormal));
angleBetweenDiscAndNormal = (math.PI * 0.5f) - math.min(angleBetweenDiscAndNormal, math.PI - angleBetweenDiscAndNormal);
float f = math.tan(angleBetweenDiscAndNormal);
float g = math.sqrt(sqrOffset + f * f * sqrOffset) / radius;
if (g < 1)
{
var angleToHorizon = math.degrees(math.asin(g));
var discTangent = math.cross(discOrientation, planeNormal);
var vectorToPointOnHorizon = Quaternion.AngleAxis(angleToHorizon, discOrientation) * discTangent;
var horizonArcLength = (90 - angleToHorizon) * 2.0f;
using (new Handles.DrawingScope(frontfacedColor))
Handles.DrawWireArc(center, discOrientation, vectorToPointOnHorizon, horizonArcLength, radius);
using (new Handles.DrawingScope(backfacedColor))
Handles.DrawWireArc(center, discOrientation, vectorToPointOnHorizon, horizonArcLength - 360, radius);
}
else
{
using (new Handles.DrawingScope(backfacedColor))
Handles.DrawWireDisc(center, discOrientation, radius);
}
}
}
}
else
{
using (new Handles.DrawingScope(backfacedColor))
{
for (int i = 0; i < 3; i++)
{
var discOrientation = discOrientations[i];
Handles.DrawWireDisc(center, discOrientation, radius);
}
}
}
}
}
}
}
fileFormatVersion: 2
guid: d4f82f07aa94f9241ad081812f8c3b1a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 30413a61e5b44d54dbd680b077804e45
timeCreated: 1678288991
\ No newline at end of file
#if UNITY_EDITOR
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(BallAndSocketJoint))]
public class BallAndSocketEditor : UnityEditor.Editor
{
protected virtual void OnSceneGUI()
{
BallAndSocketJoint ballAndSocket = (BallAndSocketJoint)target;
EditorGUI.BeginChangeCheck();
EditorUtilities.EditPivot(ballAndSocket.worldFromA, ballAndSocket.worldFromB, ballAndSocket.AutoSetConnected,
ref ballAndSocket.PositionLocal, ref ballAndSocket.PositionInConnectedEntity, ballAndSocket);
}
}
}
#endif
fileFormatVersion: 2
guid: 8bfafdfc59379ec4c86d512554577279
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(CustomPhysicsMaterialTagNames))]
[CanEditMultipleObjects]
class CustomPhysicsMaterialTagNamesEditor : BaseEditor
{
#pragma warning disable 649
[AutoPopulate(ElementFormatString = "Custom Physics Material Tag {0}", Resizable = false, Reorderable = false)]
ReorderableList m_TagNames;
#pragma warning restore 649
}
}
fileFormatVersion: 2
guid: 9a6f5e4709a915246864e50578af0cf3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using Unity.Mathematics;
using static Unity.Physics.Math;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.IMGUI.Controls;
namespace Unity.Physics.Editor
{
/// <summary>
/// Provides utilities that use Handles to set positions and axes,
/// </summary>
public class EditorUtilities
{
// Editor for a joint pivot or pivot pair
public static void EditPivot(RigidTransform worldFromA, RigidTransform worldFromB, bool lockBtoA,
ref float3 pivotA, ref float3 pivotB, Object target)
{
EditorGUI.BeginChangeCheck();
float3 pivotAinW = Handles.PositionHandle(math.transform(worldFromA, pivotA), quaternion.identity);
float3 pivotBinW;
if (lockBtoA)
{
pivotBinW = pivotAinW;
pivotB = math.transform(math.inverse(worldFromB), pivotBinW);
}
else
{
pivotBinW = Handles.PositionHandle(math.transform(worldFromB, pivotB), quaternion.identity);
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Edit joint pivot");
pivotA = math.transform(math.inverse(worldFromA), pivotAinW);
pivotB = math.transform(math.inverse(worldFromB), pivotBinW);
}
Handles.DrawLine(worldFromA.pos, pivotAinW);
Handles.DrawLine(worldFromB.pos, pivotBinW);
}
// Editor for a joint axis or axis pair
public class AxisEditor
{
// Even though we're only editing axes and not rotations, we need to track a full rotation in order to keep the rotation handle stable
private quaternion m_RefA = quaternion.identity;
private quaternion m_RefB = quaternion.identity;
// Detect changes in the object being edited to reset the reference orientations
private Object m_LastTarget;
private static bool NormalizeSafe(ref float3 x)
{
float lengthSq = math.lengthsq(x);
const float epsSq = 1e-8f;
if (math.abs(lengthSq - 1) > epsSq)
{
if (lengthSq > epsSq)
{
x *= math.rsqrt(lengthSq);
}
else
{
x = new float3(1, 0, 0);
}
return true;
}
return false;
}
private static bool NormalizePerpendicular(float3 axis, ref float3 perpendicular)
{
// make sure perpendicular is actually perpendicular to direction
float dot = math.dot(axis, perpendicular);
float absDot = math.abs(dot);
if (absDot > 1.0f - 1e-5f)
{
// parallel, choose an arbitrary perpendicular
float3 dummy;
CalculatePerpendicularNormalized(axis, out perpendicular, out dummy);
return true;
}
if (absDot > 1e-5f)
{
// reject direction
perpendicular -= dot * axis;
NormalizeSafe(ref perpendicular);
return true;
}
return NormalizeSafe(ref perpendicular);
}
public void Update(RigidTransform worldFromA, RigidTransform worldFromB, bool lockBtoA, float3 pivotA, float3 pivotB,
ref float3 directionA, ref float3 directionB, ref float3 perpendicularA, ref float3 perpendicularB, Object target)
{
// Work in world space
float3 directionAinW = math.rotate(worldFromA, directionA);
float3 directionBinW = math.rotate(worldFromB, directionB);
float3 perpendicularAinW = math.rotate(worldFromB, perpendicularA);
float3 perpendicularBinW = math.rotate(worldFromB, perpendicularB);
bool changed = false;
// If the target changed, fix up the inputs and reset the reference orientations to align with the new target's axes
if (target != m_LastTarget)
{
m_LastTarget = target;
// Enforce normalized directions
changed |= NormalizeSafe(ref directionAinW);
changed |= NormalizeSafe(ref directionBinW);
// Enforce normalized perpendiculars, orthogonal to their respective directions
changed |= NormalizePerpendicular(directionAinW, ref perpendicularAinW);
changed |= NormalizePerpendicular(directionBinW, ref perpendicularBinW);
// Calculate the rotation of the joint in A from direction and perpendicular
float3x3 rotationA = new float3x3(directionAinW, perpendicularAinW, math.cross(directionAinW, perpendicularAinW));
m_RefA = new quaternion(rotationA);
if (lockBtoA)
{
m_RefB = m_RefA;
}
else
{
// Calculate the rotation of the joint in B from direction and perpendicular
float3x3 rotationB = new float3x3(directionBinW, perpendicularBinW, math.cross(directionBinW, perpendicularBinW));
m_RefB = new quaternion(rotationB);
}
}
EditorGUI.BeginChangeCheck();
// Make rotators
quaternion oldRefA = m_RefA;
quaternion oldRefB = m_RefB;
float3 pivotAinW = math.transform(worldFromA, pivotA);
m_RefA = Handles.RotationHandle(m_RefA, pivotAinW);
float3 pivotBinW;
if (lockBtoA)
{
directionB = math.rotate(math.inverse(worldFromB), directionAinW);
perpendicularB = math.rotate(math.inverse(worldFromB), perpendicularAinW);
pivotBinW = pivotAinW;
m_RefB = m_RefA;
}
else
{
pivotBinW = math.transform(worldFromB, pivotB);
m_RefB = Handles.RotationHandle(m_RefB, pivotBinW);
}
// Apply changes from the rotators
if (EditorGUI.EndChangeCheck())
{
quaternion dqA = math.mul(m_RefA, math.inverse(oldRefA));
quaternion dqB = math.mul(m_RefB, math.inverse(oldRefB));
directionAinW = math.mul(dqA, directionAinW);
directionBinW = math.mul(dqB, directionBinW);
perpendicularAinW = math.mul(dqB, perpendicularAinW);
perpendicularBinW = math.mul(dqB, perpendicularBinW);
changed = true;
}
// Write back if the axes changed
if (changed)
{
Undo.RecordObject(target, "Edit joint axis");
directionA = math.rotate(math.inverse(worldFromA), directionAinW);
directionB = math.rotate(math.inverse(worldFromB), directionBinW);
perpendicularA = math.rotate(math.inverse(worldFromB), perpendicularAinW);
perpendicularB = math.rotate(math.inverse(worldFromB), perpendicularBinW);
}
// Draw the updated axes
float3 z = new float3(0, 0, 1); // ArrowHandleCap() draws an arrow pointing in (0, 0, 1)
Handles.ArrowHandleCap(0, pivotAinW, Quaternion.FromToRotation(z, directionAinW), HandleUtility.GetHandleSize(pivotAinW) * 0.75f, Event.current.type);
Handles.ArrowHandleCap(0, pivotAinW, Quaternion.FromToRotation(z, perpendicularAinW), HandleUtility.GetHandleSize(pivotAinW) * 0.75f, Event.current.type);
if (!lockBtoA)
{
Handles.ArrowHandleCap(0, pivotBinW, Quaternion.FromToRotation(z, directionBinW), HandleUtility.GetHandleSize(pivotBinW) * 0.75f, Event.current.type);
Handles.ArrowHandleCap(0, pivotBinW, Quaternion.FromToRotation(z, perpendicularBinW), HandleUtility.GetHandleSize(pivotBinW) * 0.75f, Event.current.type);
}
}
}
public static void EditLimits(RigidTransform worldFromA, RigidTransform worldFromB, float3 pivotA, float3 axisA, float3 axisB, float3 perpendicularA, float3 perpendicularB,
ref float minLimit, ref float maxLimit, JointAngularLimitHandle limitHandle, Object target)
{
// Transform to world space
float3 pivotAinW = math.transform(worldFromA, pivotA);
float3 axisAinW = math.rotate(worldFromA, axisA);
float3 perpendicularAinW = math.rotate(worldFromA, perpendicularA);
float3 axisBinW = math.rotate(worldFromA, axisB);
float3 perpendicularBinW = math.rotate(worldFromB, perpendicularB);
// Get rotations from joint space
// JointAngularLimitHandle uses axis = (1, 0, 0) with angle = 0 at (0, 0, 1), so choose the rotations to point those in the directions of our axis and perpendicular
float3x3 worldFromJointA = new float3x3(axisAinW, -math.cross(axisAinW, perpendicularAinW), perpendicularAinW);
float3x3 worldFromJointB = new float3x3(axisBinW, -math.cross(axisBinW, perpendicularBinW), perpendicularBinW);
float3x3 jointBFromA = math.mul(math.transpose(worldFromJointB), worldFromJointA);
// Set orientation for the angular limit control
float angle = CalculateTwistAngle(new quaternion(jointBFromA), 0); // index = 0 because axis is the first column in worldFromJoint
quaternion limitOrientation = math.mul(quaternion.AxisAngle(axisAinW, angle), new quaternion(worldFromJointA));
Matrix4x4 handleMatrix = Matrix4x4.TRS(pivotAinW, limitOrientation, Vector3.one);
float size = HandleUtility.GetHandleSize(pivotAinW) * 0.75f;
limitHandle.xMin = -maxLimit;
limitHandle.xMax = -minLimit;
limitHandle.xMotion = ConfigurableJointMotion.Limited;
limitHandle.yMotion = ConfigurableJointMotion.Locked;
limitHandle.zMotion = ConfigurableJointMotion.Locked;
limitHandle.yHandleColor = new Color(0, 0, 0, 0);
limitHandle.zHandleColor = new Color(0, 0, 0, 0);
limitHandle.radius = size;
using (new Handles.DrawingScope(handleMatrix))
{
// Draw the reference axis
float3 z = new float3(0, 0, 1); // ArrowHandleCap() draws an arrow pointing in (0, 0, 1)
Handles.ArrowHandleCap(0, float3.zero, Quaternion.FromToRotation(z, new float3(1, 0, 0)), size, Event.current.type);
// Draw the limit editor handle
EditorGUI.BeginChangeCheck();
limitHandle.DrawHandle();
if (EditorGUI.EndChangeCheck())
{
// Record the target object before setting new limits so changes can be undone/redone
Undo.RecordObject(target, "Edit joint angular limits");
minLimit = -limitHandle.xMax;
maxLimit = -limitHandle.xMin;
}
}
}
}
}
#endif
fileFormatVersion: 2
guid: 5c7e2e7874c307546bb3ab423b21a11e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_EDITOR
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(LimitedHingeJoint))]
public class LimitedHingeEditor : UnityEditor.Editor
{
private EditorUtilities.AxisEditor m_AxisEditor = new EditorUtilities.AxisEditor();
private JointAngularLimitHandle m_LimitHandle = new JointAngularLimitHandle();
public override void OnInspectorGUI()
{
LimitedHingeJoint limitedHinge = (LimitedHingeJoint)target;
EditorGUI.BeginChangeCheck();
GUILayout.BeginHorizontal();
GUILayout.Label("Editors:");
limitedHinge.EditPivots = GUILayout.Toggle(limitedHinge.EditPivots, new GUIContent("Pivot"), "Button");
limitedHinge.EditAxes = GUILayout.Toggle(limitedHinge.EditAxes, new GUIContent("Axis"), "Button");
limitedHinge.EditLimits = GUILayout.Toggle(limitedHinge.EditLimits, new GUIContent("Limits"), "Button");
GUILayout.EndHorizontal();
DrawDefaultInspector();
if (EditorGUI.EndChangeCheck())
{
SceneView.RepaintAll();
}
}
protected virtual void OnSceneGUI()
{
LimitedHingeJoint limitedHinge = (LimitedHingeJoint)target;
if (limitedHinge.EditPivots)
{
EditorUtilities.EditPivot(limitedHinge.worldFromA, limitedHinge.worldFromB, limitedHinge.AutoSetConnected,
ref limitedHinge.PositionLocal, ref limitedHinge.PositionInConnectedEntity, limitedHinge);
}
if (limitedHinge.EditAxes)
{
m_AxisEditor.Update(limitedHinge.worldFromA, limitedHinge.worldFromB,
limitedHinge.AutoSetConnected,
limitedHinge.PositionLocal, limitedHinge.PositionInConnectedEntity,
ref limitedHinge.HingeAxisLocal, ref limitedHinge.HingeAxisInConnectedEntity,
ref limitedHinge.PerpendicularAxisLocal, ref limitedHinge.PerpendicularAxisInConnectedEntity,
limitedHinge);
}
if (limitedHinge.EditLimits)
{
EditorUtilities.EditLimits(limitedHinge.worldFromA, limitedHinge.worldFromB,
limitedHinge.PositionLocal,
limitedHinge.HingeAxisLocal, limitedHinge.HingeAxisInConnectedEntity,
limitedHinge.PerpendicularAxisLocal, limitedHinge.PerpendicularAxisInConnectedEntity,
ref limitedHinge.MinAngle, ref limitedHinge.MaxAngle, m_LimitHandle, limitedHinge);
}
}
}
}
#endif
fileFormatVersion: 2
guid: f79ce4d7693ece94fb5927586cd79ad9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using Unity.Mathematics;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(PhysicsBodyAuthoring))]
[CanEditMultipleObjects]
class PhysicsBodyAuthoringEditor : BaseEditor
{
static class Content
{
public static readonly GUIContent MassLabel = EditorGUIUtility.TrTextContent("Mass");
public static readonly GUIContent CenterOfMassLabel = EditorGUIUtility.TrTextContent(
"Center of Mass", "Center of mass in the space of this body's transform."
);
public static readonly GUIContent InertiaTensorLabel = EditorGUIUtility.TrTextContent(
"Inertia Tensor", "Resistance to angular motion about each axis of rotation."
);
public static readonly GUIContent OrientationLabel = EditorGUIUtility.TrTextContent(
"Orientation", "Orientation of the body's inertia tensor in the space of its transform."
);
public static readonly GUIContent AdvancedLabel = EditorGUIUtility.TrTextContent(
"Advanced", "Advanced options"
);
}
#pragma warning disable 649
[AutoPopulate] SerializedProperty m_MotionType;
[AutoPopulate] SerializedProperty m_Smoothing;
[AutoPopulate] SerializedProperty m_Mass;
[AutoPopulate] SerializedProperty m_GravityFactor;
[AutoPopulate] SerializedProperty m_LinearDamping;
[AutoPopulate] SerializedProperty m_AngularDamping;
[AutoPopulate] SerializedProperty m_InitialLinearVelocity;
[AutoPopulate] SerializedProperty m_InitialAngularVelocity;
[AutoPopulate] SerializedProperty m_OverrideDefaultMassDistribution;
[AutoPopulate] SerializedProperty m_CenterOfMass;
[AutoPopulate] SerializedProperty m_Orientation;
[AutoPopulate] SerializedProperty m_InertiaTensor;
[AutoPopulate] SerializedProperty m_WorldIndex;
[AutoPopulate] SerializedProperty m_CustomTags;
#pragma warning restore 649
bool showAdvanced;
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_MotionType);
if (m_MotionType.intValue != (int)BodyMotionType.Static)
EditorGUILayout.PropertyField(m_Smoothing);
var dynamic = m_MotionType.intValue == (int)BodyMotionType.Dynamic;
if (dynamic)
EditorGUILayout.PropertyField(m_Mass, Content.MassLabel);
else
{
EditorGUI.BeginDisabledGroup(true);
var position = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
EditorGUI.BeginProperty(position, Content.MassLabel, m_Mass);
EditorGUI.FloatField(position, Content.MassLabel, float.PositiveInfinity);
EditorGUI.EndProperty();
EditorGUI.EndDisabledGroup();
}
if (m_MotionType.intValue == (int)BodyMotionType.Dynamic)
{
EditorGUILayout.PropertyField(m_LinearDamping, true);
EditorGUILayout.PropertyField(m_AngularDamping, true);
}
if (m_MotionType.intValue != (int)BodyMotionType.Static)
{
EditorGUILayout.PropertyField(m_InitialLinearVelocity, true);
EditorGUILayout.PropertyField(m_InitialAngularVelocity, true);
}
if (m_MotionType.intValue == (int)BodyMotionType.Dynamic)
{
EditorGUILayout.PropertyField(m_GravityFactor, true);
}
showAdvanced = EditorGUILayout.Foldout(showAdvanced, Content.AdvancedLabel);
if (showAdvanced)
{
++EditorGUI.indentLevel;
EditorGUILayout.PropertyField(m_WorldIndex);
if (m_MotionType.intValue != (int)BodyMotionType.Static)
{
EditorGUILayout.PropertyField(m_OverrideDefaultMassDistribution);
if (m_OverrideDefaultMassDistribution.boolValue)
{
++EditorGUI.indentLevel;
EditorGUILayout.PropertyField(m_CenterOfMass, Content.CenterOfMassLabel);
EditorGUI.BeginDisabledGroup(!dynamic);
if (dynamic)
{
EditorGUILayout.PropertyField(m_Orientation, Content.OrientationLabel);
EditorGUILayout.PropertyField(m_InertiaTensor, Content.InertiaTensorLabel);
}
else
{
EditorGUI.BeginDisabledGroup(true);
var position =
EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(m_InertiaTensor));
EditorGUI.BeginProperty(position, Content.InertiaTensorLabel, m_InertiaTensor);
EditorGUI.Vector3Field(position, Content.InertiaTensorLabel,
Vector3.one * float.PositiveInfinity);
EditorGUI.EndProperty();
EditorGUI.EndDisabledGroup();
}
EditorGUI.EndDisabledGroup();
--EditorGUI.indentLevel;
}
}
EditorGUILayout.PropertyField(m_CustomTags);
--EditorGUI.indentLevel;
}
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
DisplayStatusMessages();
}
MessageType m_Status;
List<string> m_StatusMessages = new List<string>(8);
void DisplayStatusMessages()
{
m_Status = MessageType.None;
m_StatusMessages.Clear();
var hierarchyStatus = StatusMessageUtility.GetHierarchyStatusMessage(targets, out var hierarchyStatusMessage);
if (!string.IsNullOrEmpty(hierarchyStatusMessage))
{
m_StatusMessages.Add(hierarchyStatusMessage);
m_Status = (MessageType)math.max((int)m_Status, (int)hierarchyStatus);
}
if (m_StatusMessages.Count > 0)
EditorGUILayout.HelpBox(string.Join("\n\n", m_StatusMessages), m_Status);
}
}
}
fileFormatVersion: 2
guid: a63bbe7a0e8f0934fb7896991b8408ce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(PhysicsCategoryNames))]
[CanEditMultipleObjects]
class PhysicsCategoryNamesEditor : BaseEditor
{
#pragma warning disable 649
[AutoPopulate(ElementFormatString = "Category {0}", Resizable = false, Reorderable = false)]
ReorderableList m_CategoryNames;
#pragma warning restore 649
}
}
fileFormatVersion: 2
guid: fcbb532fa3ab5ca4cb5005410a82cc83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics.Authoring;
using Unity.Physics.Extensions;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(PhysicsShapeAuthoring))]
[CanEditMultipleObjects]
class PhysicsShapeAuthoringEditor : BaseEditor
{
static class Styles
{
const string k_Plural = "One or more selected objects";
const string k_Singular = "This object";
public static readonly string GenericUndoMessage = L10n.Tr("Change Shape");
public static readonly string MultipleShapeTypesLabel =
L10n.Tr("Multiple shape types in current selection.");
public static readonly string PreviewGenerationNotification =
L10n.Tr("Generating collision geometry preview...");
static readonly GUIContent k_FitToRenderMeshesLabel =
EditorGUIUtility.TrTextContent("Fit to Enabled Render Meshes");
static readonly GUIContent k_FitToRenderMeshesWarningLabelSg = new GUIContent(
k_FitToRenderMeshesLabel.text,
EditorGUIUtility.Load("console.warnicon") as Texture,
L10n.Tr($"{k_Singular} has non-uniform scale. Trying to fit the shape to render meshes might produce unexpected results.")
);
static readonly GUIContent k_FitToRenderMeshesWarningLabelPl = new GUIContent(
k_FitToRenderMeshesLabel.text,
EditorGUIUtility.Load("console.warnicon") as Texture,
L10n.Tr($"{k_Plural} has non-uniform scale. Trying to fit the shape to render meshes might produce unexpected results.")
);
public static readonly GUIContent CenterLabel = EditorGUIUtility.TrTextContent("Center");
public static readonly GUIContent SizeLabel = EditorGUIUtility.TrTextContent("Size");
public static readonly GUIContent OrientationLabel = EditorGUIUtility.TrTextContent(
"Orientation", "Euler orientation in the shape's local space (ZXY order)."
);
public static readonly GUIContent CylinderSideCountLabel = EditorGUIUtility.TrTextContent("Side Count");
public static readonly GUIContent RadiusLabel = EditorGUIUtility.TrTextContent("Radius");
public static readonly GUIContent ForceUniqueLabel = EditorGUIUtility.TrTextContent(
"Force Unique",
"If set to true, then this object will always produce a unique collider for run-time during conversion. " +
"If set to false, then this object may share its collider data with other objects if they have the same inputs. " +
"You should enable this option if you plan to modify this instance's collider at run-time."
);
public static readonly GUIContent MaterialLabel = EditorGUIUtility.TrTextContent("Material");
public static readonly GUIContent SetRecommendedConvexValues = EditorGUIUtility.TrTextContent(
"Set Recommended Default Values",
"Set recommended values for convex hull generation parameters based on either render meshes or custom mesh."
);
public static GUIContent GetFitToRenderMeshesLabel(int numTargets, MessageType status) =>
status >= MessageType.Warning
? numTargets == 1 ? k_FitToRenderMeshesWarningLabelSg : k_FitToRenderMeshesWarningLabelPl
: k_FitToRenderMeshesLabel;
static readonly string[] k_NoGeometryWarning =
{
L10n.Tr($"{k_Singular} has no enabled render meshes in its hierarchy and no custom mesh assigned."),
L10n.Tr($"{k_Plural} has no enabled render meshes in their hierarchies and no custom mesh assigned.")
};
public static string GetNoGeometryWarning(int numTargets) =>
numTargets == 1 ? k_NoGeometryWarning[0] : k_NoGeometryWarning[1];
static readonly string[] k_NonReadableGeometryWarning =
{
L10n.Tr($"{k_Singular} has a non-readable mesh in its hierarchy. Move it into a sub-scene or assign a custom mesh with Read/Write enabled in its import settings if it needs to be converted at run-time."),
L10n.Tr($"{k_Plural} has a non-readable mesh in its hierarchy. Move it into a sub-scene or assign a custom mesh with Read/Write enabled in its import settings if it needs to be converted at run-time.")
};
public static string GetNonReadableGeometryWarning(int numTargets) =>
numTargets == 1 ? k_NonReadableGeometryWarning[0] : k_NonReadableGeometryWarning[1];
static readonly string[] k_MeshWithSkinnedPointsWarning =
{
L10n.Tr($"{k_Singular} is a mesh based on its render geometry, but its render geometry includes skinned points. These points will be excluded from the automatically generated shape."),
L10n.Tr($"{k_Plural} is a mesh based on its render geometry, but its render geometry includes skinned points. These points will be excluded from the automatically generated shape.")
};
public static string GetMeshWithSkinnedPointsWarning(int numTargets) =>
numTargets == 1 ? k_MeshWithSkinnedPointsWarning[0] : k_MeshWithSkinnedPointsWarning[1];
static readonly string[] k_StaticColliderStatusMessage =
{
L10n.Tr($"{k_Singular} will be considered static. Add a {ObjectNames.NicifyVariableName(typeof(PhysicsBodyAuthoring).Name)} component if you will move it at run-time."),
L10n.Tr($"{k_Plural} will be considered static. Add a {ObjectNames.NicifyVariableName(typeof(PhysicsBodyAuthoring).Name)} component if you will move them at run-time.")
};
public static string GetStaticColliderStatusMessage(int numTargets) =>
numTargets == 1 ? k_StaticColliderStatusMessage[0] : k_StaticColliderStatusMessage[1];
public static readonly string BoxCapsuleSuggestion =
L10n.Tr($"Target {ShapeType.Box} has uniform size on its two short axes and a large convex radius. Consider using a {ShapeType.Capsule} instead.");
public static readonly string BoxPlaneSuggestion =
L10n.Tr($"Target {ShapeType.Box} is flat. Consider using a {ShapeType.Plane} instead.");
public static readonly string BoxSphereSuggestion =
L10n.Tr($"Target {ShapeType.Box} has uniform size and large convex radius. Consider using a {ShapeType.Sphere} instead.");
public static readonly string CapsuleSphereSuggestion =
L10n.Tr($"Target {ShapeType.Capsule}'s diameter is equal to its height. Consider using a {ShapeType.Sphere} instead.");
public static readonly string CylinderCapsuleSuggestion =
L10n.Tr($"Target {ShapeType.Cylinder} has a large convex radius. Consider using a {ShapeType.Capsule} instead.");
public static readonly string CylinderSphereSuggestion =
L10n.Tr($"Target {ShapeType.Cylinder} has a large convex radius and its diameter is equal to its height. Consider using a {ShapeType.Sphere} instead.");
public static readonly GUIStyle Button =
new GUIStyle(EditorStyles.miniButton) { padding = new RectOffset() };
public static readonly GUIStyle ButtonDropDown =
new GUIStyle(EditorStyles.popup) { alignment = TextAnchor.MiddleCenter };
}
#pragma warning disable 649
[AutoPopulate] SerializedProperty m_ShapeType;
[AutoPopulate] SerializedProperty m_PrimitiveCenter;
[AutoPopulate] SerializedProperty m_PrimitiveSize;
[AutoPopulate] SerializedProperty m_PrimitiveOrientation;
[AutoPopulate] SerializedProperty m_Capsule;
[AutoPopulate] SerializedProperty m_Cylinder;
[AutoPopulate] SerializedProperty m_CylinderSideCount;
[AutoPopulate] SerializedProperty m_SphereRadius;
[AutoPopulate] SerializedProperty m_ConvexHullGenerationParameters;
[AutoPopulate(PropertyPath = "m_ConvexHullGenerationParameters.m_BevelRadius")] SerializedProperty m_BevelRadius;
[AutoPopulate] SerializedProperty m_MinimumSkinnedVertexWeight;
[AutoPopulate] SerializedProperty m_CustomMesh;
[AutoPopulate] SerializedProperty m_Material;
[AutoPopulate] SerializedProperty m_ForceUnique;
#pragma warning restore 649
[Flags]
enum GeometryState
{
Okay = 0,
NoGeometry = 1 << 0,
NonReadableGeometry = 1 << 1,
MeshWithSkinnedPoints = 1 << 2
}
GeometryState m_GeometryState;
int m_NumImplicitStatic;
// keep track of when the user is dragging some control to prevent continually rebuilding preview geometry
[NonSerialized]
int m_DraggingControlID;
[NonSerialized]
FitToRenderMeshesDropDown m_DropDown;
protected override void OnEnable()
{
base.OnEnable();
HashUtility.Initialize();
m_NumImplicitStatic = targets.Cast<PhysicsShapeAuthoring>().Count(
shape => shape.GetPrimaryBody() == shape.gameObject
&& shape.GetComponent<PhysicsBodyAuthoring>() == null
&& shape.GetComponent<Rigidbody>() == null
);
Undo.undoRedoPerformed += Repaint;
}
void OnDisable()
{
Undo.undoRedoPerformed -= Repaint;
SceneViewUtility.ClearNotificationInSceneView();
foreach (var preview in m_PreviewData.Values)
preview.Dispose();
if (m_DropDown != null)
m_DropDown.CloseWithoutUndo();
}
class PreviewMeshData : IDisposable
{
[BurstCompile]
struct CreateTempHullJob : IJob
{
public ConvexHullGenerationParameters GenerationParameters;
[ReadOnly]
[DeallocateOnJobCompletion]
public NativeArray<float3> Points;
public NativeArray<BlobAssetReference<Collider>> Output;
public void Execute() => Output[0] = ConvexCollider.Create(Points, GenerationParameters, CollisionFilter.Default);
}
[BurstCompile]
struct CreateTempMeshJob : IJob
{
[ReadOnly]
[DeallocateOnJobCompletion]
public NativeArray<float3> Points;
[ReadOnly]
[DeallocateOnJobCompletion]
public NativeArray<int3> Triangles;
public NativeArray<BlobAssetReference<Collider>> Output;
public void Execute() => Output[0] = MeshCollider.Create(Points, Triangles);
}
static readonly List<Vector3> s_ReusableEdges = new List<Vector3>(1024);
public Vector3[] Edges = Array.Empty<Vector3>();
public Aabb Bounds = new Aabb();
bool m_Disposed;
uint m_InputHash;
ConvexHullGenerationParameters m_HashedConvexParameters;
NativeArray<float3> m_HashedPoints = new NativeArray<float3>(0, Allocator.Persistent);
// multiple preview jobs might be running if user assigned a different mesh before previous job completed
JobHandle m_MostRecentlyScheduledJob;
Dictionary<JobHandle, NativeArray<BlobAssetReference<Collider>>> m_PreviewJobsOutput =
new Dictionary<JobHandle, NativeArray<BlobAssetReference<Collider>>>();
unsafe uint GetInputHash(
PhysicsShapeAuthoring shape,
NativeList<float3> currentPoints,
NativeArray<float3> hashedPoints,
ConvexHullGenerationParameters hashedConvexParameters,
out ConvexHullGenerationParameters currentConvexProperties
)
{
currentConvexProperties = default;
switch (shape.ShapeType)
{
case ShapeType.ConvexHull:
shape.GetBakedConvexProperties(currentPoints); // TODO: use HashableShapeInputs
currentConvexProperties = shape.ConvexHullGenerationParameters;
return math.hash(
new uint3(
(uint)shape.ShapeType,
currentConvexProperties.GetStableHash(hashedConvexParameters),
currentPoints.GetStableHash(hashedPoints)
)
);
case ShapeType.Mesh:
var triangles = new NativeList<int3>(1024, Allocator.Temp);
shape.GetBakedMeshProperties(currentPoints, triangles); // TODO: use HashableShapeInputs
return math.hash(
new uint3(
(uint)shape.ShapeType,
currentPoints.GetStableHash(hashedPoints),
math.hash(triangles.GetUnsafePtr(), UnsafeUtility.SizeOf<int3>() * triangles.Length)
)
);
default:
return (uint)shape.ShapeType;
}
}
public void SchedulePreviewIfChanged(PhysicsShapeAuthoring shape)
{
using (var currentPoints = new NativeList<float3>(65535, Allocator.Temp))
{
var hash = GetInputHash(
shape, currentPoints, m_HashedPoints, m_HashedConvexParameters, out var currentConvexParameters
);
if (m_InputHash == hash)
return;
m_InputHash = hash;
m_HashedConvexParameters = currentConvexParameters;
m_HashedPoints.Dispose();
m_HashedPoints = new NativeArray<float3>(currentPoints.Length, Allocator.Persistent);
m_HashedPoints.CopyFrom(currentPoints.AsArray());
}
if (shape.ShapeType != ShapeType.ConvexHull && shape.ShapeType != ShapeType.Mesh)
return;
// TODO: cache results per input data hash, and simply use existing data (e.g., to make undo/redo faster)
var output = new NativeArray<BlobAssetReference<Collider>>(1, Allocator.Persistent);
m_MostRecentlyScheduledJob = shape.ShapeType == ShapeType.Mesh
? ScheduleMeshPreview(shape, output)
: ScheduleConvexHullPreview(shape, output);
m_PreviewJobsOutput.Add(m_MostRecentlyScheduledJob, output);
if (m_PreviewJobsOutput.Count == 1)
{
CheckPreviewJobsForCompletion();
if (m_MostRecentlyScheduledJob.Equals(default(JobHandle)))
return;
EditorApplication.update += CheckPreviewJobsForCompletion;
EditorApplication.delayCall += () =>
{
SceneViewUtility.DisplayProgressNotification(
Styles.PreviewGenerationNotification, () => float.PositiveInfinity
);
};
}
}
JobHandle ScheduleConvexHullPreview(PhysicsShapeAuthoring shape, NativeArray<BlobAssetReference<Collider>> output)
{
var pointCloud = new NativeList<float3>(65535, Allocator.Temp);
shape.GetBakedConvexProperties(pointCloud);
if (pointCloud.Length == 0)
return default;
// copy to NativeArray because NativeList not yet compatible with DeallocateOnJobCompletion
var pointsArray = new NativeArray<float3>(
pointCloud.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory
);
pointsArray.CopyFrom(pointCloud.AsArray());
// TODO: if there is still an active job with the same input data hash, then just set it to be most recently scheduled job
return new CreateTempHullJob
{
GenerationParameters = shape.ConvexHullGenerationParameters.ToRunTime(),
Points = pointsArray,
Output = output
}.Schedule();
}
JobHandle ScheduleMeshPreview(PhysicsShapeAuthoring shape, NativeArray<BlobAssetReference<Collider>> output)
{
var points = new NativeList<float3>(1024, Allocator.Temp);
var triangles = new NativeList<int3>(1024, Allocator.Temp);
shape.GetBakedMeshProperties(points, triangles);
if (points.Length == 0 || triangles.Length == 0)
return default;
// copy to NativeArray because NativeList not yet compatible with DeallocateOnJobCompletion
var pointsArray = new NativeArray<float3>(
points.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory
);
pointsArray.CopyFrom(points.AsArray());
var triangleArray = new NativeArray<int3>(
triangles.Length, Allocator.Persistent, NativeArrayOptions.UninitializedMemory
);
triangleArray.CopyFrom(triangles.AsArray());
// TODO: if there is still an active job with the same input data hash, then just set it to be most recently scheduled job
return new CreateTempMeshJob
{
Points = pointsArray,
Triangles = triangleArray,
Output = output
}.Schedule();
}
unsafe void CheckPreviewJobsForCompletion()
{
var repaintSceneViews = false;
foreach (var job in m_PreviewJobsOutput.Keys.ToArray()) // TODO: don't allocate on heap
{
// repaint scene views to indicate progress if most recent preview job is still in the queue
var mostRecentlyScheduledJob = m_MostRecentlyScheduledJob.Equals(job);
repaintSceneViews |= mostRecentlyScheduledJob;
if (!job.IsCompleted)
continue;
var output = m_PreviewJobsOutput[job];
m_PreviewJobsOutput.Remove(job);
job.Complete();
// only populate preview edge data if not already disposed and this job was actually the most recent
if (!m_Disposed && mostRecentlyScheduledJob)
{
if (!output[0].IsCreated)
{
Edges = Array.Empty<Vector3>();
Bounds = new Aabb();
}
else
{
switch (output[0].Value.Type)
{
case ColliderType.Convex:
ref var convex = ref output[0].As<ConvexCollider>();
DrawingUtility.GetConvexColliderEdges(
ref convex, s_ReusableEdges
);
Bounds = convex.CalculateAabb();
break;
case ColliderType.Mesh:
ref var mesh = ref output[0].As<MeshCollider>();
DrawingUtility.GetMeshColliderEdges(
ref mesh, s_ReusableEdges
);
Bounds = mesh.CalculateAabb();
break;
}
Edges = s_ReusableEdges.ToArray();
}
EditorApplication.delayCall += SceneViewUtility.ClearNotificationInSceneView;
}
if (output.IsCreated)
{
if (output[0].IsCreated)
output[0].Dispose();
output.Dispose();
}
}
if (repaintSceneViews)
SceneView.RepaintAll();
if (m_PreviewJobsOutput.Count == 0)
EditorApplication.update -= CheckPreviewJobsForCompletion;
}
public void Dispose()
{
m_Disposed = true;
m_HashedPoints.Dispose();
}
}
Dictionary<PhysicsShapeAuthoring, PreviewMeshData> m_PreviewData = new Dictionary<PhysicsShapeAuthoring, PreviewMeshData>();
PreviewMeshData GetPreviewData(PhysicsShapeAuthoring shape)
{
if (shape.ShapeType != ShapeType.ConvexHull && shape.ShapeType != ShapeType.Mesh)
return null;
if (!m_PreviewData.TryGetValue(shape, out var preview))
{
preview = m_PreviewData[shape] = new PreviewMeshData();
preview.SchedulePreviewIfChanged(shape);
}
// do not generate a new preview until the user has finished dragging a control handle (e.g., scale)
if (m_DraggingControlID == 0 && !EditorGUIUtility.editingTextField)
preview.SchedulePreviewIfChanged(shape);
return preview;
}
void UpdateGeometryState()
{
m_GeometryState = GeometryState.Okay;
var skinnedPoints = new NativeList<float3>(8192, Allocator.Temp);
foreach (PhysicsShapeAuthoring shape in targets)
{
// if a custom mesh is assigned, only check it
using (var so = new SerializedObject(shape))
{
var customMesh = so.FindProperty(m_CustomMesh.propertyPath).objectReferenceValue as UnityEngine.Mesh;
if (customMesh != null)
{
m_GeometryState |= GetGeometryState(customMesh, shape.gameObject);
continue;
}
}
// otherwise check all mesh filters in the hierarchy that might be included
var geometryState = GeometryState.Okay;
using (var scope = new GetActiveChildrenScope<MeshFilter>(shape, shape.transform))
{
foreach (var meshFilter in scope.Buffer)
{
if (scope.IsChildActiveAndBelongsToShape(meshFilter, filterOutInvalid: false))
geometryState |= GetGeometryState(meshFilter.sharedMesh, shape.gameObject);
}
}
if (shape.ShapeType == ShapeType.Mesh)
{
PhysicsShapeAuthoring.GetAllSkinnedPointsInHierarchyBelongingToShape(
shape, skinnedPoints, false, default, default, default
);
if (skinnedPoints.Length > 0)
geometryState |= GeometryState.MeshWithSkinnedPoints;
}
m_GeometryState |= geometryState;
}
skinnedPoints.Dispose();
}
static GeometryState GetGeometryState(UnityEngine.Mesh mesh, GameObject host)
{
if (mesh == null)
return GeometryState.NoGeometry;
if (!mesh.IsValidForConversion(host))
return GeometryState.NonReadableGeometry;
return GeometryState.Okay;
}
public override void OnInspectorGUI()
{
var hotControl = GUIUtility.hotControl;
switch (Event.current.GetTypeForControl(hotControl))
{
case EventType.MouseDrag:
m_DraggingControlID = hotControl;
break;
case EventType.MouseUp:
m_DraggingControlID = 0;
break;
}
UpdateGeometryState();
serializedObject.Update();
UpdateStatusMessages();
EditorGUI.BeginChangeCheck();
DisplayShapeSelector();
++EditorGUI.indentLevel;
if (m_ShapeType.hasMultipleDifferentValues)
EditorGUILayout.HelpBox(Styles.MultipleShapeTypesLabel, MessageType.None);
else
{
switch ((ShapeType)m_ShapeType.intValue)
{
case ShapeType.Box:
AutomaticPrimitiveControls();
DisplayBoxControls();
break;
case ShapeType.Capsule:
AutomaticPrimitiveControls();
DisplayCapsuleControls();
break;
case ShapeType.Sphere:
AutomaticPrimitiveControls();
DisplaySphereControls();
break;
case ShapeType.Cylinder:
AutomaticPrimitiveControls();
DisplayCylinderControls();
break;
case ShapeType.Plane:
AutomaticPrimitiveControls();
DisplayPlaneControls();
break;
case ShapeType.ConvexHull:
RecommendedConvexValuesButton();
EditorGUILayout.PropertyField(m_ConvexHullGenerationParameters);
EditorGUILayout.PropertyField(m_MinimumSkinnedVertexWeight);
DisplayMeshControls();
break;
case ShapeType.Mesh:
DisplayMeshControls();
break;
default:
throw new UnimplementedShapeException((ShapeType)m_ShapeType.intValue);
}
EditorGUILayout.PropertyField(m_ForceUnique, Styles.ForceUniqueLabel);
}
--EditorGUI.indentLevel;
EditorGUILayout.LabelField(Styles.MaterialLabel);
++EditorGUI.indentLevel;
EditorGUILayout.PropertyField(m_Material);
--EditorGUI.indentLevel;
if (m_StatusMessages.Count > 0)
EditorGUILayout.HelpBox(string.Join("\n\n", m_StatusMessages), m_Status);
if (EditorGUI.EndChangeCheck())
serializedObject.ApplyModifiedProperties();
}
void RecommendedConvexValuesButton()
{
EditorGUI.BeginDisabledGroup(
(m_GeometryState & GeometryState.NoGeometry) == GeometryState.NoGeometry ||
EditorUtility.IsPersistent(target)
);
var rect = EditorGUI.IndentedRect(
EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight, EditorStyles.miniButton)
);
var buttonLabel = Styles.SetRecommendedConvexValues;
if (GUI.Button(rect, buttonLabel, Styles.Button))
{
Undo.RecordObjects(targets, buttonLabel.text);
foreach (PhysicsShapeAuthoring shape in targets)
{
shape.InitializeConvexHullGenerationParameters();
EditorUtility.SetDirty(shape);
}
}
EditorGUI.EndDisabledGroup();
}
MessageType m_GeometryStatus;
List<string> m_GeometryStatusMessages = new List<string>();
HashSet<string> m_ShapeSuggestions = new HashSet<string>();
MessageType m_Status;
List<string> m_StatusMessages = new List<string>(8);
MessageType m_MatrixStatus;
List<MatrixState> m_MatrixStates = new List<MatrixState>();
void UpdateStatusMessages()
{
m_Status = MessageType.None;
m_StatusMessages.Clear();
if (m_NumImplicitStatic != 0)
m_StatusMessages.Add(Styles.GetStaticColliderStatusMessage(targets.Length));
m_ShapeSuggestions.Clear();
foreach (PhysicsShapeAuthoring shape in targets)
{
const float k_Epsilon = HashableShapeInputs.k_DefaultLinearPrecision;
switch (shape.ShapeType)
{
case ShapeType.Box:
var box = shape.GetBakedBoxProperties();
var max = math.cmax(box.Size);
var min = math.cmin(box.Size);
if (min < k_Epsilon)
m_ShapeSuggestions.Add(Styles.BoxPlaneSuggestion);
else if (math.abs(box.BevelRadius - min * 0.5f) < k_Epsilon)
{
if (math.abs(max - min) < k_Epsilon)
m_ShapeSuggestions.Add(Styles.BoxSphereSuggestion);
else if (math.abs(math.lengthsq(box.Size - new float3(min)) - math.pow(max - min, 2f)) < k_Epsilon)
m_ShapeSuggestions.Add(Styles.BoxCapsuleSuggestion);
}
break;
case ShapeType.Capsule:
var capsule = shape.GetBakedCapsuleProperties();
if (math.abs(capsule.Height - 2f * capsule.Radius) < k_Epsilon)
m_ShapeSuggestions.Add(Styles.CapsuleSphereSuggestion);
break;
case ShapeType.Cylinder:
var cylinder = shape.GetBakedCylinderProperties();
if (math.abs(cylinder.BevelRadius - cylinder.Radius) < k_Epsilon)
{
m_ShapeSuggestions.Add(math.abs(cylinder.Height - 2f * cylinder.Radius) < k_Epsilon
? Styles.CylinderSphereSuggestion
: Styles.CylinderCapsuleSuggestion);
}
break;
}
}
foreach (var suggestion in m_ShapeSuggestions)
m_StatusMessages.Add(suggestion);
var hierarchyStatus = StatusMessageUtility.GetHierarchyStatusMessage(targets, out var hierarchyStatusMessage);
if (!string.IsNullOrEmpty(hierarchyStatusMessage))
{
m_StatusMessages.Add(hierarchyStatusMessage);
m_Status = (MessageType)math.max((int)m_Status, (int)hierarchyStatus);
}
m_MatrixStates.Clear();
foreach (var t in targets)
{
var localToWorld = (float4x4)(t as Component).transform.localToWorldMatrix;
m_MatrixStates.Add(ManipulatorUtility.GetMatrixState(ref localToWorld));
}
m_MatrixStatus = StatusMessageUtility.GetMatrixStatusMessage(m_MatrixStates, out var matrixStatusMessage);
if (m_MatrixStatus != MessageType.None)
{
m_StatusMessages.Add(matrixStatusMessage);
m_Status = (MessageType)math.max((int)m_Status, (int)m_MatrixStatus);
}
m_GeometryStatus = MessageType.None;
m_GeometryStatusMessages.Clear();
if ((m_GeometryState & GeometryState.NoGeometry) == GeometryState.NoGeometry)
{
m_GeometryStatusMessages.Add(Styles.GetNoGeometryWarning(targets.Length));
m_GeometryStatus = (MessageType)math.max((int)m_GeometryStatus, (int)MessageType.Error);
}
if ((m_GeometryState & GeometryState.NonReadableGeometry) == GeometryState.NonReadableGeometry)
{
m_GeometryStatusMessages.Add(Styles.GetNonReadableGeometryWarning(targets.Length));
m_GeometryStatus = (MessageType)math.max((int)m_GeometryStatus, (int)MessageType.Warning);
}
if ((m_GeometryState & GeometryState.MeshWithSkinnedPoints) == GeometryState.MeshWithSkinnedPoints)
{
m_GeometryStatusMessages.Add(Styles.GetMeshWithSkinnedPointsWarning(targets.Length));
m_GeometryStatus = (MessageType)math.max((int)m_GeometryStatus, (int)MessageType.Warning);
}
}
void DisplayShapeSelector()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_ShapeType);
if (!EditorGUI.EndChangeCheck())
return;
Undo.RecordObjects(targets, Styles.GenericUndoMessage);
foreach (PhysicsShapeAuthoring shape in targets)
{
switch ((ShapeType)m_ShapeType.intValue)
{
case ShapeType.Box:
shape.SetBox(shape.GetBoxProperties(out var orientation), orientation);
break;
case ShapeType.Capsule:
shape.SetCapsule(shape.GetCapsuleProperties());
break;
case ShapeType.Sphere:
shape.SetSphere(shape.GetSphereProperties(out orientation), orientation);
break;
case ShapeType.Cylinder:
shape.SetCylinder(shape.GetCylinderProperties(out orientation), orientation);
break;
case ShapeType.Plane:
shape.GetPlaneProperties(out var center, out var size2D, out orientation);
shape.SetPlane(center, size2D, orientation);
break;
case ShapeType.ConvexHull:
case ShapeType.Mesh:
return;
default:
throw new UnimplementedShapeException((ShapeType)m_ShapeType.intValue);
}
EditorUtility.SetDirty(shape);
}
GUIUtility.ExitGUI();
}
void AutomaticPrimitiveControls()
{
EditorGUI.BeginDisabledGroup(
(m_GeometryState & GeometryState.NoGeometry) == GeometryState.NoGeometry || EditorUtility.IsPersistent(target)
);
var buttonLabel = Styles.GetFitToRenderMeshesLabel(targets.Length, m_MatrixStatus);
var rect = EditorGUI.IndentedRect(
EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight, EditorStyles.miniButton)
);
if (GUI.Button(rect, buttonLabel, Styles.ButtonDropDown))
m_DropDown = FitToRenderMeshesDropDown.Show(rect, buttonLabel.text, m_MinimumSkinnedVertexWeight);
EditorGUI.EndDisabledGroup();
}
class FitToRenderMeshesDropDown : EditorWindow
{
static class Styles
{
public const float WindowWidth = 400f;
public const float LabelWidth = 200f;
public static GUIStyle Button => PhysicsShapeAuthoringEditor.Styles.Button;
}
static class Content
{
public static readonly string ApplyLabel = L10n.Tr("Apply");
public static readonly string CancelLabel = L10n.Tr("Cancel");
}
bool m_ApplyChanges;
bool m_ClosedWithoutUndo;
int m_UndoGroup;
SerializedProperty m_MinimumSkinnedVertexWeight;
public static FitToRenderMeshesDropDown Show(
Rect buttonRect, string title, SerializedProperty minimumSkinnedVertexWeight
)
{
var window = CreateInstance<FitToRenderMeshesDropDown>();
window.titleContent = EditorGUIUtility.TrTextContent(title);
window.m_UndoGroup = Undo.GetCurrentGroup();
window.m_MinimumSkinnedVertexWeight = minimumSkinnedVertexWeight;
var size = new Vector2(
math.max(buttonRect.width, Styles.WindowWidth),
(EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing) * 3f
);
window.maxSize = window.minSize = size;
window.ShowAsDropDown(GUIUtility.GUIToScreenRect(buttonRect), size);
return window;
}
void OnGUI()
{
var labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth = Styles.LabelWidth;
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_MinimumSkinnedVertexWeight);
if (EditorGUI.EndChangeCheck())
ApplyChanges();
EditorGUIUtility.labelWidth = labelWidth;
GUILayout.FlexibleSpace();
var buttonRect = GUILayoutUtility.GetRect(0f, EditorGUIUtility.singleLineHeight);
var buttonLeft = new Rect(buttonRect)
{
width = 0.5f * (buttonRect.width - EditorGUIUtility.standardVerticalSpacing)
};
var buttonRight = new Rect(buttonLeft)
{
x = buttonLeft.xMax + EditorGUIUtility.standardVerticalSpacing
};
var close = false;
buttonRect = Application.platform == RuntimePlatform.OSXEditor ? buttonLeft : buttonRight;
if (
GUI.Button(buttonRect, Content.CancelLabel, Styles.Button)
|| Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape
)
{
close = true;
}
buttonRect = Application.platform == RuntimePlatform.OSXEditor ? buttonRight : buttonLeft;
if (GUI.Button(buttonRect, Content.ApplyLabel, Styles.Button))
{
close = true;
m_ApplyChanges = true;
}
if (close)
{
Close();
EditorGUIUtility.ExitGUI();
}
}
void ApplyChanges()
{
m_MinimumSkinnedVertexWeight.serializedObject.ApplyModifiedProperties();
Undo.RecordObjects(m_MinimumSkinnedVertexWeight.serializedObject.targetObjects, titleContent.text);
foreach (PhysicsShapeAuthoring shape in m_MinimumSkinnedVertexWeight.serializedObject.targetObjects)
{
using (var so = new SerializedObject(shape))
{
shape.FitToEnabledRenderMeshes(
so.FindProperty(m_MinimumSkinnedVertexWeight.propertyPath).floatValue
);
EditorUtility.SetDirty(shape);
}
}
m_MinimumSkinnedVertexWeight.serializedObject.Update();
}
public void CloseWithoutUndo()
{
m_ApplyChanges = true;
Close();
}
void OnDestroy()
{
if (m_ApplyChanges)
ApplyChanges();
else
Undo.RevertAllDownToGroup(m_UndoGroup);
}
}
void DisplayBoxControls()
{
EditorGUILayout.PropertyField(m_PrimitiveSize, Styles.SizeLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveCenter, Styles.CenterLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveOrientation, Styles.OrientationLabel, true);
EditorGUILayout.PropertyField(m_BevelRadius);
}
void DisplayCapsuleControls()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_Capsule);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObjects(targets, Styles.GenericUndoMessage);
foreach (PhysicsShapeAuthoring shape in targets)
{
shape.SetCapsule(shape.GetCapsuleProperties());
EditorUtility.SetDirty(shape);
}
}
EditorGUILayout.PropertyField(m_PrimitiveCenter, Styles.CenterLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveOrientation, Styles.OrientationLabel, true);
}
void DisplaySphereControls()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_SphereRadius, Styles.RadiusLabel);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObjects(targets, Styles.GenericUndoMessage);
foreach (PhysicsShapeAuthoring shape in targets)
{
shape.SetSphere(shape.GetSphereProperties(out EulerAngles orientation), orientation);
EditorUtility.SetDirty(shape);
}
}
EditorGUILayout.PropertyField(m_PrimitiveCenter, Styles.CenterLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveOrientation, Styles.OrientationLabel, true);
}
void DisplayCylinderControls()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_Cylinder);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObjects(targets, Styles.GenericUndoMessage);
foreach (PhysicsShapeAuthoring shape in targets)
{
shape.SetCylinder(shape.GetCylinderProperties(out var orientation), orientation);
EditorUtility.SetDirty(shape);
}
}
EditorGUILayout.PropertyField(m_PrimitiveCenter, Styles.CenterLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveOrientation, Styles.OrientationLabel, true);
EditorGUILayout.PropertyField(m_CylinderSideCount, Styles.CylinderSideCountLabel);
EditorGUILayout.PropertyField(m_BevelRadius);
}
void DisplayPlaneControls()
{
EditorGUILayout.PropertyField(m_PrimitiveSize, Styles.SizeLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveCenter, Styles.CenterLabel, true);
EditorGUILayout.PropertyField(m_PrimitiveOrientation, Styles.OrientationLabel, true);
}
void DisplayMeshControls()
{
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_CustomMesh);
if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
}
if (m_GeometryStatusMessages.Count > 0)
EditorGUILayout.HelpBox(string.Join("\n\n", m_GeometryStatusMessages), m_GeometryStatus);
}
static readonly BeveledBoxBoundsHandle s_Box = new BeveledBoxBoundsHandle();
static readonly PhysicsCapsuleBoundsHandle s_Capsule =
new PhysicsCapsuleBoundsHandle { heightAxis = CapsuleBoundsHandle.HeightAxis.Z };
static readonly BeveledCylinderBoundsHandle s_Cylinder = new BeveledCylinderBoundsHandle();
static readonly PhysicsSphereBoundsHandle s_Sphere = new PhysicsSphereBoundsHandle();
static readonly BoxBoundsHandle s_Plane =
new BoxBoundsHandle { axes = PrimitiveBoundsHandle.Axes.X | PrimitiveBoundsHandle.Axes.Z };
static readonly Color k_ShapeHandleColor = new Color32(145, 244, 139, 210);
static readonly Color k_ShapeHandleColorDisabled = new Color32(84, 200, 77, 140);
void OnSceneGUI()
{
var hotControl = GUIUtility.hotControl;
switch (Event.current.GetTypeForControl(hotControl))
{
case EventType.MouseDrag:
m_DraggingControlID = hotControl;
break;
case EventType.MouseUp:
m_DraggingControlID = 0;
break;
}
var shape = target as PhysicsShapeAuthoring;
var handleColor = shape.enabled ? k_ShapeHandleColor : k_ShapeHandleColorDisabled;
var handleMatrix = shape.GetShapeToWorldMatrix();
using (new Handles.DrawingScope(handleColor, handleMatrix))
{
switch (shape.ShapeType)
{
case ShapeType.Box:
var boxGeometry = shape.GetBakedBoxProperties();
s_Box.bevelRadius = boxGeometry.BevelRadius;
s_Box.center = float3.zero;
s_Box.size = boxGeometry.Size;
EditorGUI.BeginChangeCheck();
{
using (new Handles.DrawingScope(math.mul(Handles.matrix, float4x4.TRS(boxGeometry.Center, boxGeometry.Orientation, 1f))))
s_Box.DrawHandle();
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(shape, Styles.GenericUndoMessage);
shape.SetBakedBoxSize(s_Box.size, s_Box.bevelRadius);
}
break;
case ShapeType.Capsule:
s_Capsule.center = float3.zero;
var capsuleGeometry = shape.GetBakedCapsuleProperties();
s_Capsule.height = capsuleGeometry.Height;
s_Capsule.radius = capsuleGeometry.Radius;
EditorGUI.BeginChangeCheck();
{
using (new Handles.DrawingScope(math.mul(Handles.matrix, float4x4.TRS(capsuleGeometry.Center, capsuleGeometry.Orientation, 1f))))
s_Capsule.DrawHandle();
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(shape, Styles.GenericUndoMessage);
shape.SetBakedCapsuleSize(s_Capsule.height, s_Capsule.radius);
}
break;
case ShapeType.Sphere:
var sphereGeometry = shape.GetBakedSphereProperties(out EulerAngles orientation);
s_Sphere.center = float3.zero;
s_Sphere.radius = sphereGeometry.Radius;
EditorGUI.BeginChangeCheck();
{
using (new Handles.DrawingScope(math.mul(Handles.matrix, float4x4.TRS(sphereGeometry.Center, orientation, 1f))))
s_Sphere.DrawHandle();
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(shape, Styles.GenericUndoMessage);
shape.SetBakedSphereRadius(s_Sphere.radius);
}
break;
case ShapeType.Cylinder:
var cylinderGeometry = shape.GetBakedCylinderProperties();
s_Cylinder.center = float3.zero;
s_Cylinder.height = cylinderGeometry.Height;
s_Cylinder.radius = cylinderGeometry.Radius;
s_Cylinder.sideCount = cylinderGeometry.SideCount;
s_Cylinder.bevelRadius = cylinderGeometry.BevelRadius;
EditorGUI.BeginChangeCheck();
{
using (new Handles.DrawingScope(math.mul(Handles.matrix, float4x4.TRS(cylinderGeometry.Center, cylinderGeometry.Orientation, 1f))))
s_Cylinder.DrawHandle();
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(shape, Styles.GenericUndoMessage);
shape.SetBakedCylinderSize(s_Cylinder.height, s_Cylinder.radius, s_Cylinder.bevelRadius);
}
break;
case ShapeType.Plane:
shape.GetPlaneProperties(out var center, out var size2, out orientation);
s_Plane.center = float3.zero;
s_Plane.size = new float3(size2.x, 0f, size2.y);
EditorGUI.BeginChangeCheck();
{
var m = math.mul(shape.transform.localToWorldMatrix, float4x4.TRS(center, orientation, 1f));
using (new Handles.DrawingScope(m))
s_Plane.DrawHandle();
var right = math.mul(m, new float4 { x = 1f }).xyz;
var forward = math.mul(m, new float4 { z = 1f }).xyz;
var normal = math.cross(math.normalizesafe(forward), math.normalizesafe(right))
* 0.5f * math.lerp(math.length(right) * size2.x, math.length(forward) * size2.y, 0.5f);
using (new Handles.DrawingScope(float4x4.identity))
Handles.DrawLine(m.c3.xyz, m.c3.xyz + normal);
}
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(shape, Styles.GenericUndoMessage);
shape.SetBakedPlaneSize(((float3)s_Plane.size).xz);
}
break;
case ShapeType.ConvexHull:
if (Event.current.type != EventType.Repaint)
break;
var points = GetPreviewData(shape).Edges;
// TODO: follow transformation until new preview is generated if e.g., user is dragging handles
if (points.Length > 0)
Handles.DrawLines(points);
break;
case ShapeType.Mesh:
if (Event.current.type != EventType.Repaint)
break;
points = GetPreviewData(shape).Edges;
if (points.Length > 0)
Handles.DrawLines(points);
break;
default:
throw new UnimplementedShapeException(shape.ShapeType);
}
}
}
// ReSharper disable once UnusedMember.Global - magic method called by unity inspector
public bool HasFrameBounds()
{
return true;
}
static Bounds TransformBounds(Bounds localBounds, float4x4 matrix)
{
var center = new float4(localBounds.center, 1);
Bounds bounds = new Bounds(math.mul(matrix, center).xyz, Vector3.zero);
var extent = new float4(localBounds.extents, 0);
for (int i = 0; i < 8; ++i)
{
extent.x = (i & 1) == 0 ? -extent.x : extent.x;
extent.y = (i & 2) == 0 ? -extent.y : extent.y;
extent.z = (i & 4) == 0 ? -extent.z : extent.z;
var worldPoint = math.mul(matrix, center + extent).xyz;
bounds.Encapsulate(worldPoint);
}
return bounds;
}
// ReSharper disable once UnusedMember.Global - magic method called by unity inspector
public Bounds OnGetFrameBounds()
{
var shape = target as PhysicsShapeAuthoring;
var shapeMatrix = shape.GetShapeToWorldMatrix();
Bounds bounds = new Bounds();
switch (shape.ShapeType)
{
case ShapeType.Box:
var boxGeometry = shape.GetBakedBoxProperties();
bounds = new Bounds(float3.zero, boxGeometry.Size);
bounds = TransformBounds(bounds, float4x4.TRS(boxGeometry.Center, boxGeometry.Orientation, 1f));
break;
case ShapeType.Capsule:
var capsuleGeometry = shape.GetBakedCapsuleProperties();
var cd = capsuleGeometry.Radius * 2;
bounds = new Bounds(float3.zero, new float3(cd, cd, capsuleGeometry.Height));
bounds = TransformBounds(bounds, float4x4.TRS(capsuleGeometry.Center, capsuleGeometry.Orientation, 1f));
break;
case ShapeType.Sphere:
var sphereGeometry = shape.GetBakedSphereProperties(out var orientation);
var sd = sphereGeometry.Radius * 2;
bounds = new Bounds(sphereGeometry.Center, new float3(sd, sd, sd));
break;
case ShapeType.Cylinder:
var cylinderGeometry = shape.GetBakedCylinderProperties();
var cyld = cylinderGeometry.Radius * 2;
bounds = new Bounds(float3.zero, new float3(cyld, cyld, cylinderGeometry.Height));
bounds = TransformBounds(bounds, float4x4.TRS(cylinderGeometry.Center, cylinderGeometry.Orientation, 1f));
break;
case ShapeType.Plane:
shape.GetPlaneProperties(out var center, out var size2, out orientation);
bounds = new Bounds(float3.zero, new float3(size2.x, 0, size2.y));
bounds = TransformBounds(bounds, float4x4.TRS(center, orientation, 1f));
break;
case ShapeType.ConvexHull:
case ShapeType.Mesh:
var previewData = GetPreviewData(shape);
if (previewData != null)
bounds = new Bounds(previewData.Bounds.Center, previewData.Bounds.Extents);
break;
default:
throw new UnimplementedShapeException(shape.ShapeType);
}
return TransformBounds(bounds, shapeMatrix);
}
}
}
fileFormatVersion: 2
guid: 209b4a4e54f038844baf182ae186f813
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using Unity.Mathematics;
using Unity.Physics.Authoring;
namespace Unity.Physics.Editor
{
[CustomEditor(typeof(RagdollJoint))]
public class RagdollJointEditor : UnityEditor.Editor
{
private EditorUtilities.AxisEditor m_AxisEditor = new EditorUtilities.AxisEditor();
private JointAngularLimitHandle m_LimitHandle = new JointAngularLimitHandle();
public override void OnInspectorGUI()
{
RagdollJoint ragdoll = (RagdollJoint)target;
EditorGUI.BeginChangeCheck();
GUILayout.BeginVertical();
GUILayout.Space(10.0f);
GUILayout.BeginHorizontal();
GUILayout.Label("Editors:");
ragdoll.EditPivots = GUILayout.Toggle(ragdoll.EditPivots, new GUIContent("Pivot"), "Button");
ragdoll.EditAxes = GUILayout.Toggle(ragdoll.EditAxes, new GUIContent("Axis"), "Button");
ragdoll.EditLimits = GUILayout.Toggle(ragdoll.EditLimits, new GUIContent("Limits"), "Button");
GUILayout.EndHorizontal();
GUILayout.Space(10.0f);
GUILayout.EndVertical();
DrawDefaultInspector();
if (EditorGUI.EndChangeCheck())
{
SceneView.RepaintAll();
}
}
private static void DrawCone(float3 point, float3 axis, float angle, Color color)
{
#if UNITY_EDITOR
Handles.color = color;
float3 dir;
float scale = Math.NormalizeWithLength(axis, out dir);
float3 arm;
{
float3 perp1, perp2;
Math.CalculatePerpendicularNormalized(dir, out perp1, out perp2);
arm = math.mul(quaternion.AxisAngle(perp1, angle), dir) * scale;
}
const int res = 16;
quaternion q = quaternion.AxisAngle(dir, 2.0f * (float)math.PI / res);
for (int i = 0; i < res; i++)
{
float3 nextArm = math.mul(q, arm);
Handles.DrawLine(point, point + arm);
Handles.DrawLine(point + arm, point + nextArm);
arm = nextArm;
}
#endif
}
protected virtual void OnSceneGUI()
{
RagdollJoint ragdoll = (RagdollJoint)target;
bool drawCones = false;
if (ragdoll.EditPivots)
{
EditorUtilities.EditPivot(ragdoll.worldFromA, ragdoll.worldFromB, ragdoll.AutoSetConnected,
ref ragdoll.PositionLocal, ref ragdoll.PositionInConnectedEntity, ragdoll);
}
if (ragdoll.EditAxes)
{
m_AxisEditor.Update(ragdoll.worldFromA, ragdoll.worldFromB, ragdoll.AutoSetConnected,
ragdoll.PositionLocal, ragdoll.PositionInConnectedEntity, ref ragdoll.TwistAxisLocal, ref ragdoll.TwistAxisInConnectedEntity,
ref ragdoll.PerpendicularAxisLocal, ref ragdoll.PerpendicularAxisInConnectedEntity, ragdoll);
drawCones = true;
}
if (ragdoll.EditLimits)
{
EditorUtilities.EditLimits(ragdoll.worldFromA, ragdoll.worldFromB, ragdoll.PositionLocal, ragdoll.TwistAxisLocal, ragdoll.TwistAxisInConnectedEntity,
ragdoll.PerpendicularAxisLocal, ragdoll.PerpendicularAxisInConnectedEntity, ref ragdoll.MinTwistAngle, ref ragdoll.MaxTwistAngle, m_LimitHandle, ragdoll);
}
if (drawCones)
{
float3 pivotB = math.transform(ragdoll.worldFromB, ragdoll.PositionInConnectedEntity);
float3 axisB = math.rotate(ragdoll.worldFromB, ragdoll.TwistAxisInConnectedEntity);
DrawCone(pivotB, axisB, math.radians(ragdoll.MaxConeAngle), Color.yellow);
float3 perpendicularB = math.rotate(ragdoll.worldFromB, ragdoll.PerpendicularAxisInConnectedEntity);
DrawCone(pivotB, perpendicularB, math.radians(ragdoll.MinPerpendicularAngle + 90f), Color.red);
DrawCone(pivotB, perpendicularB, math.radians(ragdoll.MaxPerpendicularAngle + 90f), Color.red);
}
}
}
}
#endif
fileFormatVersion: 2
guid: 4c97c008c29536647add5a287db56ae2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 23d0032aba561954aaf56c65acf751bd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
abstract class BaseDrawer : PropertyDrawer
{
protected abstract bool IsCompatible(SerializedProperty property);
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return IsCompatible(property)
? EditorGUI.GetPropertyHeight(property)
: EditorGUIUtility.singleLineHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (IsCompatible(property))
DoGUI(position, property, label);
else
EditorGUIControls.DisplayCompatibilityWarning(position, label, ObjectNames.NicifyVariableName(GetType().Name));
}
protected abstract void DoGUI(Rect position, SerializedProperty property, GUIContent label);
}
}
fileFormatVersion: 2
guid: a4ce107efdd5d5f439469b8b109f601f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomPropertyDrawer(typeof(EnumFlagsAttribute))]
class EnumFlagsDrawer : BaseDrawer
{
protected override bool IsCompatible(SerializedProperty property)
{
return property.propertyType == SerializedPropertyType.Enum;
}
protected override void DoGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
var value = property.longValue;
EditorGUI.BeginChangeCheck();
value = Convert.ToInt64(
EditorGUI.EnumFlagsField(position, label, (Enum)Enum.ToObject(fieldInfo.FieldType, value))
);
if (EditorGUI.EndChangeCheck())
property.longValue = value;
EditorGUI.EndProperty();
}
}
}
fileFormatVersion: 2
guid: 91d983b20a4beed4794e82ce61acb452
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomPropertyDrawer(typeof(EulerAngles))]
class EulerAnglesDrawer : BaseDrawer
{
protected override bool IsCompatible(SerializedProperty property) => true;
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
var value = property.FindPropertyRelative(nameof(EulerAngles.Value));
return EditorGUI.GetPropertyHeight(value);
}
protected override void DoGUI(Rect position, SerializedProperty property, GUIContent label)
{
var value = property.FindPropertyRelative(nameof(EulerAngles.Value));
EditorGUI.PropertyField(position, value, label, true);
}
}
}
fileFormatVersion: 2
guid: aa19ca1ba7846e443a44ba0fff644d17
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomPropertyDrawer(typeof(ExpandChildrenAttribute))]
class ExpandChildrenDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
property.isExpanded = true;
return EditorGUI.GetPropertyHeight(property)
- EditorGUIUtility.standardVerticalSpacing
- EditorGUIUtility.singleLineHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var endProperty = property.GetEndProperty();
var childProperty = property.Copy();
childProperty.NextVisible(true);
while (!SerializedProperty.EqualContents(childProperty, endProperty))
{
position.height = EditorGUI.GetPropertyHeight(childProperty);
OnChildPropertyGUI(position, childProperty);
position.y += position.height + EditorGUIUtility.standardVerticalSpacing;
childProperty.NextVisible(false);
}
}
protected virtual void OnChildPropertyGUI(Rect position, SerializedProperty childProperty)
{
EditorGUI.PropertyField(position, childProperty, true);
}
}
}
fileFormatVersion: 2
guid: 0c02598cdac1be04a9039046cc3b8459
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomPropertyDrawer(typeof(PhysicsMaterialCoefficient))]
class PhysicsMaterialCoefficientDrawer : BaseDrawer
{
static class Styles
{
public const float PopupWidth = 100f;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) =>
EditorGUIUtility.singleLineHeight;
protected override bool IsCompatible(SerializedProperty property) => true;
protected override void DoGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(
new Rect(position) { xMax = position.xMax - Styles.PopupWidth },
property.FindPropertyRelative("Value"),
label
);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
EditorGUI.PropertyField(
new Rect(position) { xMin = position.xMax - Styles.PopupWidth + EditorGUIUtility.standardVerticalSpacing },
property.FindPropertyRelative("CombineMode"),
GUIContent.none
);
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
}
}
fileFormatVersion: 2
guid: 637c07be1ce65064687a822ad33de1aa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomPropertyDrawer(typeof(PhysicsMaterialProperties))]
class PhysicsMaterialPropertiesDrawer : BaseDrawer
{
static class Content
{
public static readonly GUIContent AdvancedGroupFoldout = EditorGUIUtility.TrTextContent("Advanced");
public static readonly GUIContent BelongsToLabel = EditorGUIUtility.TrTextContent(
"Belongs To",
"Specifies the categories to which this object belongs."
);
public static readonly GUIContent CollidesWithLabel = EditorGUIUtility.TrTextContent(
"Collides With",
"Specifies the categories of objects with which this object will collide, " +
"or with which it will raise events if intersecting a trigger."
);
public static readonly GUIContent CollisionFilterGroupFoldout =
EditorGUIUtility.TrTextContent("Collision Filter");
public static readonly GUIContent CustomFlagsLabel =
EditorGUIUtility.TrTextContent("Custom Tags", "Specify custom tags to read at run-time.");
public static readonly GUIContent FrictionLabel = EditorGUIUtility.TrTextContent(
"Friction",
"Specifies how resistant the body is to motion when sliding along other surfaces, " +
"as well as what value should be used when colliding with an object that has a different value."
);
public static readonly GUIContent RestitutionLabel = EditorGUIUtility.TrTextContent(
"Restitution",
"Specifies how bouncy the object will be when colliding with other surfaces, " +
"as well as what value should be used when colliding with an object that has a different value."
);
public static readonly GUIContent CollisionResponseLabel = EditorGUIUtility.TrTextContent(
"Collision Response",
"Specifies whether the shape should collide normally, raise trigger events when intersecting other shapes, " +
"collide normally and raise notifications of collision events with other shapes, " +
"or completely ignore collisions (but still move and intercept queries)."
);
}
const string k_CollisionFilterGroupKey = "m_BelongsToCategories";
const string k_AdvancedGroupKey = "m_CustomMaterialTags";
Dictionary<string, SerializedObject> m_SerializedTemplates = new Dictionary<string, SerializedObject>();
SerializedProperty GetTemplateValueProperty(SerializedProperty property)
{
var key = property.propertyPath;
var template = property.FindPropertyRelative("m_Template").objectReferenceValue;
SerializedObject serializedTemplate;
if (
!m_SerializedTemplates.TryGetValue(key, out serializedTemplate)
|| serializedTemplate?.targetObject != template
)
m_SerializedTemplates[key] = serializedTemplate = template == null ? null : new SerializedObject(template);
serializedTemplate?.Update();
return serializedTemplate?.FindProperty("m_Value");
}
void FindToggleAndValueProperties(
SerializedProperty property, SerializedProperty templateValueProperty, string relativePath,
out SerializedProperty toggle, out SerializedProperty value
)
{
var relative = property.FindPropertyRelative(relativePath);
toggle = relative.FindPropertyRelative("m_Override");
value = toggle.boolValue || templateValueProperty == null
? relative.FindPropertyRelative("m_Value")
: templateValueProperty.FindPropertyRelative(relativePath).FindPropertyRelative("m_Value");
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
var templateValueProperty = GetTemplateValueProperty(property);
// m_CollisionResponse, collision filter foldout, advanced foldout
var height = 3f * EditorGUIUtility.singleLineHeight + 2f * EditorGUIUtility.standardVerticalSpacing;
// m_BelongsTo, m_CollidesWith
var group = property.FindPropertyRelative(k_CollisionFilterGroupKey);
if (group.isExpanded)
height += 2f * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
// m_CustomTags
group = property.FindPropertyRelative(k_AdvancedGroupKey);
if (group.isExpanded)
height += (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
// m_Template
if (property.FindPropertyRelative("m_SupportsTemplate").boolValue)
height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
// m_Friction, m_Restitution
FindToggleAndValueProperties(property, templateValueProperty, "m_CollisionResponse", out _, out var collisionResponse);
// Check if regular collider
CollisionResponsePolicy collisionResponseEnum = (CollisionResponsePolicy)collisionResponse.intValue;
if (collisionResponseEnum == CollisionResponsePolicy.Collide ||
collisionResponseEnum == CollisionResponsePolicy.CollideRaiseCollisionEvents)
height += 2f * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
return height;
}
protected override bool IsCompatible(SerializedProperty property) => true;
static void DisplayOverridableProperty(
Rect position, GUIContent label, SerializedProperty toggle, SerializedProperty value, bool templateAssigned
)
{
if (templateAssigned)
{
var labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth -= 16f + EditorGUIUtility.standardVerticalSpacing;
var togglePosition = new Rect(position) { width = EditorGUIUtility.labelWidth + 16f + EditorGUIUtility.standardVerticalSpacing };
EditorGUI.PropertyField(togglePosition, toggle, label);
EditorGUIUtility.labelWidth = labelWidth;
EditorGUI.BeginDisabledGroup(!toggle.boolValue);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
EditorGUI.PropertyField(new Rect(position) { xMin = togglePosition.xMax }, value, GUIContent.none, true);
EditorGUI.indentLevel = indent;
EditorGUI.EndDisabledGroup();
}
else
{
EditorGUI.PropertyField(position, value, label, true);
}
}
protected override void DoGUI(Rect position, SerializedProperty property, GUIContent label)
{
var template = property.FindPropertyRelative("m_Template");
var templateAssigned = template.objectReferenceValue != null;
var supportsTemplate = property.FindPropertyRelative("m_SupportsTemplate");
if (supportsTemplate.boolValue)
{
position.height = EditorGUI.GetPropertyHeight(template);
EditorGUI.PropertyField(position, template);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
}
var templateValue = GetTemplateValueProperty(property);
FindToggleAndValueProperties(property, templateValue, "m_CollisionResponse", out var collisionResponseDropDown, out var collisionResponse);
position.height = EditorGUIUtility.singleLineHeight;
DisplayOverridableProperty(position, Content.CollisionResponseLabel, collisionResponseDropDown, collisionResponse, templateAssigned);
SerializedProperty toggle;
// Check if regular collider
CollisionResponsePolicy collisionResponseEnum = (CollisionResponsePolicy)collisionResponse.intValue;
if (collisionResponseEnum == CollisionResponsePolicy.Collide ||
collisionResponseEnum == CollisionResponsePolicy.CollideRaiseCollisionEvents)
{
FindToggleAndValueProperties(property, templateValue, "m_Friction", out toggle, out var friction);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
DisplayOverridableProperty(position, Content.FrictionLabel, toggle, friction, templateAssigned);
FindToggleAndValueProperties(property, templateValue, "m_Restitution", out toggle, out var restitution);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
DisplayOverridableProperty(position, Content.RestitutionLabel, toggle, restitution, templateAssigned);
}
// collision filter group
var collisionFilterGroup = property.FindPropertyRelative(k_CollisionFilterGroupKey);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
collisionFilterGroup.isExpanded =
EditorGUI.Foldout(position, collisionFilterGroup.isExpanded, Content.CollisionFilterGroupFoldout, true);
if (collisionFilterGroup.isExpanded)
{
++EditorGUI.indentLevel;
FindToggleAndValueProperties(property, templateValue, "m_BelongsToCategories", out toggle, out var belongsTo);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
DisplayOverridableProperty(position, Content.BelongsToLabel, toggle, belongsTo, templateAssigned);
FindToggleAndValueProperties(property, templateValue, "m_CollidesWithCategories", out toggle, out var collidesWith);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
DisplayOverridableProperty(position, Content.CollidesWithLabel, toggle, collidesWith, templateAssigned);
--EditorGUI.indentLevel;
}
// advanced group
var advancedGroup = property.FindPropertyRelative(k_AdvancedGroupKey);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
advancedGroup.isExpanded =
EditorGUI.Foldout(position, advancedGroup.isExpanded, Content.AdvancedGroupFoldout, true);
if (advancedGroup.isExpanded)
{
++EditorGUI.indentLevel;
FindToggleAndValueProperties(property, templateValue, "m_CustomMaterialTags", out toggle, out var customFlags);
position.y = position.yMax + EditorGUIUtility.standardVerticalSpacing;
position.height = EditorGUIUtility.singleLineHeight;
DisplayOverridableProperty(position, Content.CustomFlagsLabel, toggle, customFlags, templateAssigned);
--EditorGUI.indentLevel;
}
}
}
}
fileFormatVersion: 2
guid: 72400ec801359f34e9b82e3be224cde5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[CustomPropertyDrawer(typeof(SoftRangeAttribute))]
class SoftRangeDrawer : BaseDrawer
{
protected override bool IsCompatible(SerializedProperty property)
{
return property.propertyType == SerializedPropertyType.Float;
}
protected override void DoGUI(Rect position, SerializedProperty property, GUIContent label)
{
var attr = attribute as SoftRangeAttribute;
EditorGUIControls.SoftSlider(
position, label, property, attr.SliderMin, attr.SliderMax, attr.TextFieldMin, attr.TextFieldMax
);
}
}
}
fileFormatVersion: 2
guid: b3973ec625484cb418fb92f5b2bbffdd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using System.Linq;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
abstract class TagsDrawer<T> : PropertyDrawer where T : ScriptableObject, ITagNames
{
static class Styles
{
public static readonly string EverythingName = L10n.Tr("Everything");
public static readonly string MixedName = L10n.Tr("Mixed...");
public static readonly string NothingName = L10n.Tr("Nothing");
public static readonly string MultipleAssetsTooltip =
L10n.Tr("Multiple {0} assets found. UI will display labels defined in {1}.");
public static readonly GUIContent MultipleAssetsWarning =
new GUIContent { image = EditorGUIUtility.Load("console.warnicon") as Texture };
}
protected abstract int MaxNumCategories { get; }
protected abstract string DefaultCategoryName { get; }
internal string FirstChildPropertyPath { get; set; } // TODO: remove when all usages of bool[] are migrated
string DefaultFormatString => L10n.Tr($"(Undefined {DefaultCategoryName})");
string[] DefaultOptions =>
m_DefaultOptions ?? (
m_DefaultOptions =
Enumerable.Range(0, MaxNumCategories)
.Select(i => string.Format(DefaultFormatString, i))
.ToArray()
);
string[] m_DefaultOptions;
string[] GetOptions()
{
if (m_Options != null)
return m_Options;
var guids = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
m_NamesAssets = guids
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<T>)
.Where(c => c != null)
.ToArray();
m_Options = m_NamesAssets.FirstOrDefault()?.TagNames.ToArray() ?? DefaultOptions;
for (var i = 0; i < m_Options.Length; ++i)
{
if (string.IsNullOrEmpty(m_Options[i]))
m_Options[i] = DefaultOptions[i];
m_Options[i] = $"{i}: {m_Options[i]}";
}
return m_Options;
}
string[] m_Options;
static string GetButtonLabel(int value, IReadOnlyList<string> optionNames)
{
switch (value)
{
case 0:
return Styles.NothingName;
case ~0:
return Styles.EverythingName;
default:
{
for (var i = 0; i < 32; i++)
{
if (value == 1 << i)
return optionNames[i];
}
break;
}
}
return Styles.MixedName;
}
T[] m_NamesAssets;
// TODO: remove when all usages of bool[] are migrated
SerializedProperty GetFirstChildProperty(SerializedProperty property)
{
if (!string.IsNullOrEmpty(FirstChildPropertyPath))
return property.FindPropertyRelative(FirstChildPropertyPath);
var sp = property.Copy();
sp.NextVisible(true);
return sp;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (m_NamesAssets?.Length > 1)
position.xMax -= EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
EditorGUI.BeginProperty(position, label, property);
var controlPosition = EditorGUI.PrefixLabel(position, label);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
var showMixed = EditorGUI.showMixedValue;
var value = 0;
var everything = 0;
var sp = GetFirstChildProperty(property);
for (int i = 0, count = MaxNumCategories; i < count; ++i)
{
EditorGUI.showMixedValue |= sp.hasMultipleDifferentValues;
value |= sp.boolValue ? 1 << i : 0;
everything |= 1 << i;
sp.NextVisible(false);
}
// in case size is smaller than 32
if (value == everything)
value = ~0;
var options = GetOptions();
if (
EditorGUI.DropdownButton(
controlPosition,
EditorGUIUtility.TrTempContent(GetButtonLabel(value, options)),
FocusType.Passive,
EditorStyles.popup
)
)
{
var menu = new GenericMenu();
menu.AddItem(
new GUIContent(Styles.NothingName),
value == 0,
() =>
{
sp = GetFirstChildProperty(property);
for (int i = 0, count = MaxNumCategories; i < count; ++i)
{
sp.boolValue = false;
sp.NextVisible(false);
}
sp.serializedObject.ApplyModifiedProperties();
}
);
menu.AddItem(
new GUIContent(Styles.EverythingName),
value == ~0,
() =>
{
sp = GetFirstChildProperty(property);
for (int i = 0, count = MaxNumCategories; i < count; ++i)
{
sp.boolValue = true;
sp.NextVisible(false);
}
sp.serializedObject.ApplyModifiedProperties();
}
);
for (var option = 0; option < options.Length; ++option)
{
var callbackValue = option;
menu.AddItem(
EditorGUIUtility.TrTextContent(options[option]),
((1 << option) & value) != 0,
args =>
{
var changedBitAndValue = (KeyValuePair<int, bool>)args;
sp = GetFirstChildProperty(property);
for (int i = 0, count = changedBitAndValue.Key; i < count; ++i)
sp.NextVisible(false);
sp.boolValue = changedBitAndValue.Value;
sp.serializedObject.ApplyModifiedProperties();
},
new KeyValuePair<int, bool>(callbackValue, ((1 << option) & value) == 0)
);
}
menu.AddSeparator(string.Empty);
menu.AddItem(
EditorGUIUtility.TrTempContent($"Edit {ObjectNames.NicifyVariableName(typeof(T).Name)}"),
false,
() =>
{
if (m_NamesAssets.Length > 0)
Selection.activeObject = m_NamesAssets[0];
else
{
var assetPath = AssetDatabase.GenerateUniqueAssetPath($"Assets/{typeof(T).Name}.asset");
AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<T>(), assetPath);
Selection.activeObject = AssetDatabase.LoadAssetAtPath<T>(assetPath);
m_Options = null;
}
}
);
menu.DropDown(controlPosition);
}
EditorGUI.showMixedValue = showMixed;
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
if (m_NamesAssets?.Length > 1)
{
var id = GUIUtility.GetControlID(FocusType.Passive);
if (Event.current.type == EventType.Repaint)
{
position.width = EditorGUIUtility.singleLineHeight;
position.x = controlPosition.xMax + EditorGUIUtility.standardVerticalSpacing;
Styles.MultipleAssetsWarning.tooltip = string.Format(
Styles.MultipleAssetsTooltip,
ObjectNames.NicifyVariableName(typeof(T).Name),
m_NamesAssets.FirstOrDefault(n => n != null)?.name
);
GUIStyle.none.Draw(position, Styles.MultipleAssetsWarning, id);
}
}
}
}
[CustomPropertyDrawer(typeof(CustomPhysicsBodyTags))]
class CustomBodyTagsDrawer : TagsDrawer<CustomPhysicsBodyTagNames>
{
protected override string DefaultCategoryName => "Custom Physics Body Tag";
protected override int MaxNumCategories => 8;
}
[CustomPropertyDrawer(typeof(CustomPhysicsMaterialTags))]
class CustomMaterialTagsDrawer : TagsDrawer<CustomPhysicsMaterialTagNames>
{
protected override string DefaultCategoryName => "Custom Physics Material Tag";
protected override int MaxNumCategories => 8;
}
[CustomPropertyDrawer(typeof(PhysicsCategoryTags))]
class PhysicsCategoryTagsDrawer : TagsDrawer<PhysicsCategoryNames>
{
protected override string DefaultCategoryName => "Physics Category";
protected override int MaxNumCategories => 32;
}
}
fileFormatVersion: 2
guid: bacae2b76edd4224d8ccf21bbeb71833
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
{
"name": "Unity.Physics.Custom.Editor",
"references": [
"Unity.Burst",
"Unity.Collections",
"Unity.Entities",
"Unity.Mathematics",
"Unity.Physics",
"Unity.Physics.Editor",
"Unity.Physics.Hybrid",
"Unity.Physics.Samples",
"Unity.Physics.Custom"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
}
fileFormatVersion: 2
guid: dde4aa253ec0b874ba280d1bde6b5386
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: f3d7894b5b13854409e8c11b2c933f3e
timeCreated: 1678290090
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Unity.Mathematics;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
[InitializeOnLoad]
static class EditorGUIControls
{
static EditorGUIControls()
{
if (k_SoftSlider == null)
Debug.LogException(new MissingMemberException("Could not find expected signature of EditorGUI.Slider() for soft slider."));
}
static class Styles
{
public static readonly string CompatibilityWarning = L10n.Tr("Not compatible with {0}.");
}
public static void DisplayCompatibilityWarning(Rect position, GUIContent label, string incompatibleType)
{
EditorGUI.HelpBox(
EditorGUI.PrefixLabel(position, label),
string.Format(Styles.CompatibilityWarning, incompatibleType),
MessageType.Error
);
}
static readonly MethodInfo k_SoftSlider = typeof(EditorGUI).GetMethod(
"Slider",
BindingFlags.Static | BindingFlags.NonPublic,
null,
new[]
{
typeof(Rect), // position
typeof(GUIContent), // label
typeof(float), // value
typeof(float), // sliderMin
typeof(float), // sliderMax
typeof(float), // textFieldMin
typeof(float) // textFieldMax
},
Array.Empty<ParameterModifier>()
);
static readonly object[] k_SoftSliderArgs = new object[7];
public static void SoftSlider(
Rect position, GUIContent label, SerializedProperty property,
float sliderMin, float sliderMax,
float textFieldMin, float textFieldMax
)
{
if (property.propertyType != SerializedPropertyType.Float)
{
DisplayCompatibilityWarning(position, label, property.propertyType.ToString());
}
else if (k_SoftSlider == null)
{
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(position, property, label);
if (EditorGUI.EndChangeCheck())
property.floatValue = math.clamp(property.floatValue, textFieldMin, textFieldMax);
}
else
{
k_SoftSliderArgs[0] = position;
k_SoftSliderArgs[1] = label;
k_SoftSliderArgs[2] = property.floatValue;
k_SoftSliderArgs[3] = sliderMin;
k_SoftSliderArgs[4] = sliderMax;
k_SoftSliderArgs[5] = textFieldMin;
k_SoftSliderArgs[6] = textFieldMax;
EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
var result = k_SoftSlider.Invoke(null, k_SoftSliderArgs);
if (EditorGUI.EndChangeCheck())
property.floatValue = (float)result;
EditorGUI.EndProperty();
}
}
}
}
fileFormatVersion: 2
guid: 871e6b9236392b347a91f460fd84f976
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Editor
{
enum MatrixState
{
UniformScale,
NonUniformScale,
ZeroScale,
NotValidTRS
}
static class ManipulatorUtility
{
public static MatrixState GetMatrixState(ref float4x4 localToWorld)
{
if (
localToWorld.c0.w != 0f
|| localToWorld.c1.w != 0f
|| localToWorld.c2.w != 0f
|| localToWorld.c3.w != 1f
)
return MatrixState.NotValidTRS;
var m = new float3x3(localToWorld.c0.xyz, localToWorld.c1.xyz, localToWorld.c2.xyz);
var lossyScale = new float3(math.length(m.c0.xyz), math.length(m.c1.xyz), math.length(m.c2.xyz));
if (math.determinant(m) < 0f)
lossyScale.x *= -1f;
if (math.lengthsq(lossyScale) == 0f)
return MatrixState.ZeroScale;
return math.abs(math.cmax(lossyScale)) - math.abs(math.cmin(lossyScale)) > 0.000001f
? MatrixState.NonUniformScale
: MatrixState.UniformScale;
}
}
}
fileFormatVersion: 2
guid: 1ed6267b3a6f75e4aa4aca986451797e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
static class SceneViewUtility
{
static class Styles
{
public static readonly GUIStyle ProgressBarTrack = new GUIStyle
{
fixedHeight = 4f,
normal = new GUIStyleState { background = Texture2D.whiteTexture }
};
public static readonly GUIStyle ProgressBarIndicator = new GUIStyle
{
fixedHeight = 4f,
normal = new GUIStyleState { background = Texture2D.whiteTexture }
};
public static readonly GUIStyle SceneViewStatusMessage = new GUIStyle("NotificationBackground")
{
fontSize = EditorStyles.label.fontSize
};
static Styles() => SceneViewStatusMessage.padding = SceneViewStatusMessage.border;
}
const string k_NotificationsPrefKey = "SceneView/Tools/Notifications";
const bool k_DefaultNotifications = true;
const string k_NotificationSpeedPrefKey = "SceneView/Tools/Notification Speed";
const float k_DefaultNotificationsSpeed = 20f;
const float k_NotificationDuration = 1f;
const float k_NotificationFadeInTime = 0.04f;
const float k_NotificationFadeOutTime = 0.2f;
static readonly AnimationCurve k_NotificationFadeCurve = new AnimationCurve
{
keys = new[]
{
new Keyframe { time = 0f, value = 0f, outTangent = 1f / k_NotificationFadeInTime },
new Keyframe { time = k_NotificationFadeInTime, value = 1f, inTangent = 0f, outTangent = 0f },
new Keyframe { time = k_NotificationDuration - k_NotificationFadeOutTime, value = 1f, inTangent = 0f, outTangent = 0f },
new Keyframe { time = k_NotificationDuration, value = 0f, inTangent = -1f / k_NotificationFadeOutTime }
},
postWrapMode = WrapMode.Clamp,
preWrapMode = WrapMode.Clamp
};
const float k_IndeterminateProgressCurveDuration = 2f;
static readonly AnimationCurve k_IndeterminateProgressCurveLeftMargin = new AnimationCurve
{
keys = new[]
{
new Keyframe { time = 0f, value = 0f, inTangent = 0f, outTangent = 0f },
new Keyframe { time = k_IndeterminateProgressCurveDuration / 2f, value = 0.25f, inTangent = 0f, outTangent = 0f },
new Keyframe { time = k_IndeterminateProgressCurveDuration, value = 1f, inTangent = 0f, outTangent = 0f }
},
postWrapMode = WrapMode.Loop,
preWrapMode = WrapMode.Loop
};
static readonly AnimationCurve k_IndeterminateProgressCurveRightMargin = new AnimationCurve
{
keys = new[]
{
new Keyframe { time = 0f, value = 1f, inTangent = 0f, outTangent = 0f },
new Keyframe { time = k_IndeterminateProgressCurveDuration / 2f, value = 0f, inTangent = 0f, outTangent = 0f },
new Keyframe { time = k_IndeterminateProgressCurveDuration, value = 0f, inTangent = 0f, outTangent = 0f }
},
postWrapMode = WrapMode.Loop,
preWrapMode = WrapMode.Loop
};
static string s_StatusMessage;
static DateTime s_StartTime;
static bool s_IsTemporary;
static Func<float> s_GetProgress;
public static void DisplayProgressNotification(string message, Func<float> getProgress) =>
// insert an extra line to make room for progress bar
DisplayNotificationInSceneView(getProgress == null ? message : $"{message}\n", false, getProgress);
public static void DisplayPersistentNotification(string message) =>
DisplayNotificationInSceneView(message, false, null);
public static void DisplayTemporaryNotification(string message) =>
DisplayNotificationInSceneView(message, true, null);
static void DisplayNotificationInSceneView(string message, bool temporary, Func<float> getProgress)
{
s_StatusMessage = message ?? string.Empty;
s_StartTime = DateTime.Now;
s_IsTemporary = temporary;
s_GetProgress = getProgress;
ClearNotificationInSceneView();
SceneView.duringSceneGui += ToolNotificationCallback;
SceneView.RepaintAll();
}
static void ToolNotificationCallback(SceneView obj)
{
if (Camera.current == null)
return;
var duration = math.max(s_StatusMessage.Length, 1)
/ EditorPrefs.GetFloat(k_NotificationSpeedPrefKey, k_DefaultNotificationsSpeed);
var t = (float)(DateTime.Now - s_StartTime).TotalSeconds;
if (
s_IsTemporary
&& (t >= duration || !EditorPrefs.GetBool(k_NotificationsPrefKey, k_DefaultNotifications))
)
{
ClearNotificationInSceneView();
}
else
{
Handles.BeginGUI();
var color = GUI.color;
var progress = s_GetProgress?.Invoke() ?? 0f;
GUI.color *=
new Color(1f, 1f, 1f, math.max(k_NotificationFadeCurve.Evaluate(math.abs(t) / duration), progress));
var rect = new Rect { size = Camera.current.pixelRect.size / EditorGUIUtility.pixelsPerPoint };
using (new GUILayout.AreaScope(rect))
using (new GUILayout.HorizontalScope())
{
GUILayout.FlexibleSpace();
using (new GUILayout.VerticalScope())
{
GUILayout.Space(rect.height * 0.75f);
GUILayout.FlexibleSpace();
var maxWidth = rect.width * 0.5f;
GUILayout.Box(s_StatusMessage, Styles.SceneViewStatusMessage, GUILayout.MaxWidth(maxWidth));
if (s_GetProgress != null)
{
rect = GUILayoutUtility.GetLastRect();
rect = Styles.SceneViewStatusMessage.padding.Remove(rect);
rect.y = rect.yMax - Styles.ProgressBarTrack.fixedHeight;
rect.height = Styles.ProgressBarTrack.fixedHeight;
var c = GUI.color;
GUI.color *= Color.black;
GUI.Box(rect, GUIContent.none, Styles.ProgressBarTrack);
GUI.color = c;
if (progress >= 0f && progress <= 1f)
{
rect.width *= progress;
}
else
{
var w = rect.width;
rect.xMin = rect.xMin + w * k_IndeterminateProgressCurveLeftMargin.Evaluate(t);
rect.xMax = rect.xMax - w * k_IndeterminateProgressCurveRightMargin.Evaluate(t);
}
GUI.Box(rect, GUIContent.none, Styles.ProgressBarIndicator);
}
GUILayout.FlexibleSpace();
}
GUILayout.FlexibleSpace();
}
GUI.color = color;
Handles.EndGUI();
}
SceneView.RepaintAll();
}
public static void ClearNotificationInSceneView() => SceneView.duringSceneGui -= ToolNotificationCallback;
}
}
fileFormatVersion: 2
guid: b7c9bbfa7889d6e4faa42c14d33bebb7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections.Generic;
using System.Linq;
using Unity.Physics.Authoring;
using UnityEditor;
using UnityEngine;
namespace Unity.Physics.Editor
{
static class StatusMessageUtility
{
public static MessageType GetHierarchyStatusMessage(IReadOnlyList<UnityEngine.Object> targets, out string statusMessage)
{
statusMessage = string.Empty;
if (targets.Count == 0)
return MessageType.None;
var numChildTargets = 0;
foreach (Component c in targets)
{
// hierarchy roots and leaf shapes do not emit a message
if (
c == null
|| c.transform.parent == null
|| PhysicsShapeExtensions.GetPrimaryBody(c.gameObject) != c.gameObject
)
continue;
var targetType = c.GetType();
// only bodies (both explicit and implicit static bodies) will emit a message
if (
targetType == typeof(PhysicsBodyAuthoring)
|| targetType == typeof(Rigidbody)
|| c.GetComponent<PhysicsBodyAuthoring>() == null
&& c.GetComponent<Rigidbody>() == null
)
++numChildTargets;
}
switch (numChildTargets)
{
case 0:
return MessageType.None;
case 1:
statusMessage =
L10n.Tr("Target will be un-parented during the conversion process in order to take part in physics simulation.");
return MessageType.Warning;
default:
statusMessage =
L10n.Tr("One or more targets will be un-parented during the conversion process in order to take part in physics simulation.");
return MessageType.Warning;
}
}
public static MessageType GetMatrixStatusMessage(
IReadOnlyList<MatrixState> matrixStates, out string statusMessage
)
{
statusMessage = string.Empty;
if (matrixStates.Contains(MatrixState.NotValidTRS))
{
statusMessage = L10n.Tr(
matrixStates.Count == 1
? "Target's local-to-world matrix is not a valid transformation."
: "One or more targets' local-to-world matrices are not valid transformations."
);
return MessageType.Error;
}
if (matrixStates.Contains(MatrixState.ZeroScale))
{
statusMessage =
L10n.Tr(matrixStates.Count == 1 ? "Target has zero scale." : "One or more targets has zero scale.");
return MessageType.Warning;
}
if (matrixStates.Contains(MatrixState.NonUniformScale))
{
statusMessage = L10n.Tr(
matrixStates.Count == 1
? "Target has non-uniform scale. Shape data will be transformed during conversion in order to bake scale into the run-time format."
: "One or more targets has non-uniform scale. Shape data will be transformed during conversion in order to bake scale into the run-time format."
);
return MessageType.Warning;
}
return MessageType.None;
}
}
}
fileFormatVersion: 2
guid: 73b942099bb387a48abd183643304f85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 0daf7b2549ab2f04c8a53849098d77e3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Unity.Physics.Custom.Editor")]
[assembly: InternalsVisibleTo("Unity.Physics.Custom.EditModeTests")]
fileFormatVersion: 2
guid: 79534194088d466faf51dedb0dbb3012
timeCreated: 1680051514
\ No newline at end of file
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
[RequireComponent(typeof(PhysicsBodyAuthoring))]
public abstract class BaseBodyPairConnector : MonoBehaviour
{
public PhysicsBodyAuthoring LocalBody => GetComponent<PhysicsBodyAuthoring>();
public PhysicsBodyAuthoring ConnectedBody;
public RigidTransform worldFromA => LocalBody == null
? RigidTransform.identity
: Math.DecomposeRigidBodyTransform(LocalBody.transform.localToWorldMatrix);
public RigidTransform worldFromB => ConnectedBody == null
? RigidTransform.identity
: Math.DecomposeRigidBodyTransform(ConnectedBody.transform.localToWorldMatrix);
public Entity EntityA { get; set; }
public Entity EntityB { get; set; }
void OnEnable()
{
// included so tick box appears in Editor
}
}
}
fileFormatVersion: 2
guid: 239c8ffb2d0d90043a794cea1df207f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 67021bc32b354a27adca79ce72cc0632
timeCreated: 1678114562
\ No newline at end of file
fileFormatVersion: 2
guid: debd1c7da217451682429a0a443b3fb4
timeCreated: 1678225532
\ No newline at end of file
using System.Collections.Generic;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Physics.Extensions;
using Unity.Physics.GraphicsIntegration;
using Unity.Transforms;
using UnityEngine;
namespace Unity.Physics.Authoring
{
[TemporaryBakingType]
public struct PhysicsBodyAuthoringData : IComponentData
{
public bool IsDynamic;
public float Mass;
public bool OverrideDefaultMassDistribution;
public MassDistribution CustomMassDistribution;
}
class PhysicsBodyAuthoringBaker : BasePhysicsBaker<PhysicsBodyAuthoring>
{
internal List<UnityEngine.Collider> colliderComponents = new List<UnityEngine.Collider>();
internal List<PhysicsShapeAuthoring> physicsShapeComponents = new List<PhysicsShapeAuthoring>();
public override void Bake(PhysicsBodyAuthoring authoring)
{
// Priority is to Legacy Components. Ignore if baked by Legacy.
if (GetComponent<Rigidbody>() || GetComponent<UnityEngine.Collider>())
{
return;
}
var entity = GetEntity(TransformUsageFlags.Dynamic);
// To process later in the Baking System
AddComponent(entity, new PhysicsBodyAuthoringData
{
IsDynamic = (authoring.MotionType == BodyMotionType.Dynamic),
Mass = authoring.Mass,
OverrideDefaultMassDistribution = authoring.OverrideDefaultMassDistribution,
CustomMassDistribution = authoring.CustomMassDistribution
});
AddSharedComponent(entity, new PhysicsWorldIndex(authoring.WorldIndex));
var bodyTransform = GetComponent<Transform>();
var motionType = authoring.MotionType;
var hasSmoothing = authoring.Smoothing != BodySmoothing.None;
PostProcessTransform(bodyTransform, motionType);
var customTags = authoring.CustomTags;
if (!customTags.Equals(CustomPhysicsBodyTags.Nothing))
AddComponent(entity, new PhysicsCustomTags { Value = customTags.Value });
// Check that there is at least one collider in the hierarchy to add these three
GetComponentsInChildren(colliderComponents);
GetComponentsInChildren(physicsShapeComponents);
if (colliderComponents.Count > 0 || physicsShapeComponents.Count > 0)
{
AddComponent(entity, new PhysicsCompoundData()
{
AssociateBlobToBody = false,
ConvertedBodyInstanceID = authoring.GetInstanceID(),
Hash = default,
});
AddComponent<PhysicsRootBaked>(entity);
AddComponent<PhysicsCollider>(entity);
}
if (authoring.MotionType == BodyMotionType.Static || IsStatic())
return;
var massProperties = MassProperties.UnitSphere;
AddComponent(entity, authoring.MotionType == BodyMotionType.Dynamic ?
PhysicsMass.CreateDynamic(massProperties, authoring.Mass) :
PhysicsMass.CreateKinematic(massProperties));
var physicsVelocity = new PhysicsVelocity
{
Linear = authoring.InitialLinearVelocity,
Angular = authoring.InitialAngularVelocity
};
AddComponent(entity, physicsVelocity);
if (authoring.MotionType == BodyMotionType.Dynamic)
{
// TODO make these optional in editor?
AddComponent(entity, new PhysicsDamping
{
Linear = authoring.LinearDamping,
Angular = authoring.AngularDamping
});
if (authoring.GravityFactor != 1)
{
AddComponent(entity, new PhysicsGravityFactor
{
Value = authoring.GravityFactor
});
}
}
else if (authoring.MotionType == BodyMotionType.Kinematic)
{
AddComponent(entity, new PhysicsGravityFactor
{
Value = 0
});
}
if (hasSmoothing)
{
AddComponent(entity, new PhysicsGraphicalSmoothing());
if (authoring.Smoothing == BodySmoothing.Interpolation)
{
AddComponent(entity, new PhysicsGraphicalInterpolationBuffer
{
PreviousTransform = Math.DecomposeRigidBodyTransform(bodyTransform.localToWorldMatrix),
PreviousVelocity = physicsVelocity,
});
}
}
}
}
[RequireMatchingQueriesForUpdate]
[UpdateAfter(typeof(EndColliderBakingSystem))]
[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]
public partial struct PhysicsBodyBakingSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var entityManager = state.EntityManager;
// Fill in the mass properties based on custom mass properties for bodies without colliders
foreach (var(physicsMass, bodyData, entity) in
SystemAPI.Query<RefRW<PhysicsMass>, RefRO<PhysicsBodyAuthoringData>>()
.WithNone<PhysicsCollider>()
.WithEntityAccess()
.WithOptions(EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabledEntities))
{
physicsMass.ValueRW = CreatePhysicsMass(entityManager, entity, bodyData.ValueRO, MassProperties.UnitSphere);
}
// Fill in the mass properties based on collider and custom mass properties if provided.
foreach (var(physicsMass, bodyData, collider, entity) in
SystemAPI.Query<RefRW<PhysicsMass>, RefRO<PhysicsBodyAuthoringData>, RefRO<PhysicsCollider>>()
.WithEntityAccess()
.WithOptions(EntityQueryOptions.IncludePrefab | EntityQueryOptions.IncludeDisabledEntities))
{
physicsMass.ValueRW = CreatePhysicsMass(entityManager, entity, bodyData.ValueRO,
collider.ValueRO.MassProperties, true);
}
}
private PhysicsMass CreatePhysicsMass(EntityManager entityManager, in Entity entity,
in PhysicsBodyAuthoringData inBodyData, in MassProperties inMassProperties, in bool hasCollider = false)
{
var massProperties = inMassProperties;
var scale = 1f;
// Scale the provided mass properties by the LocalTransform.Scale value to create the correct
// initial mass distribution for the rigid body.
if (entityManager.HasComponent<LocalTransform>(entity))
{
var localTransform = entityManager.GetComponentData<LocalTransform>(entity);
scale = localTransform.Scale;
massProperties.Scale(scale);
}
// Override the mass properties with user-provided values if specified
if (inBodyData.OverrideDefaultMassDistribution)
{
massProperties.MassDistribution = inBodyData.CustomMassDistribution;
if (hasCollider)
{
// Increase the angular expansion factor to account for the shift in center of mass
massProperties.AngularExpansionFactor += math.length(massProperties.MassDistribution.Transform.pos -
inBodyData.CustomMassDistribution.Transform.pos);
}
}
// Create the physics mass properties. Among others, this scales the unit mass inertia tensor
// by the scalar mass of the rigid body.
var physicsMass = inBodyData.IsDynamic ?
PhysicsMass.CreateDynamic(massProperties, inBodyData.Mass) :
PhysicsMass.CreateKinematic(massProperties);
// Now, apply inverse scale to the final, baked physics mass properties in order to prevent invalid simulated mass properties
// caused by runtime scaling of the mass properties later on while building the physics world.
physicsMass = physicsMass.ApplyScale(math.rcp(scale));
return physicsMass;
}
}
}
fileFormatVersion: 2
guid: 922a37a81b1c6cc4da69a1148c8d2988
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Profiling;
namespace Unity.Physics.Authoring
{
class PhysicsShapeBaker : BaseColliderBaker<PhysicsShapeAuthoring>
{
public static List<PhysicsShapeAuthoring> physicsShapeComponents = new List<PhysicsShapeAuthoring>();
public static List<UnityEngine.Collider> colliderComponents = new List<UnityEngine.Collider>();
bool ShouldConvertShape(PhysicsShapeAuthoring authoring)
{
return authoring.enabled;
}
private GameObject GetPrimaryBody(GameObject shape, out bool hasBodyComponent, out bool isStaticBody)
{
var pb = FindFirstEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_PhysicsBodiesBuffer);
var rb = FindFirstEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_RigidbodiesBuffer);
hasBodyComponent = (pb != null || rb != null);
isStaticBody = false;
if (pb != null)
{
return rb == null ? pb.gameObject :
pb.transform.IsChildOf(rb.transform) ? pb.gameObject : rb.gameObject;
}
if (rb != null)
return rb.gameObject;
// for implicit static shape, first see if it is part of static optimized hierarchy
isStaticBody = FindTopmostStaticEnabledAncestor(shape, out var topStatic);
if (topStatic != null)
return topStatic;
// otherwise, find topmost enabled Collider or PhysicsShapeAuthoring
var topCollider = FindTopmostEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_CollidersBuffer);
var topShape = FindTopmostEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_ShapesBuffer);
return topCollider == null
? topShape == null ? shape.gameObject : topShape
: topShape == null
? topCollider
: topShape.transform.IsChildOf(topCollider.transform)
? topCollider
: topShape;
}
ShapeComputationDataBaking GetInputDataFromAuthoringComponent(PhysicsShapeAuthoring shape, Entity colliderEntity)
{
GameObject shapeGameObject = shape.gameObject;
var body = GetPrimaryBody(shapeGameObject, out bool hasBodyComponent, out bool isStaticBody);
var child = shapeGameObject;
var shapeInstanceID = shape.GetInstanceID();
var bodyEntity = GetEntity(body, TransformUsageFlags.Dynamic);
// prepare the static root
if (isStaticBody)
{
var staticRootMarker = CreateAdditionalEntity(TransformUsageFlags.Dynamic, true, "StaticRootBakeMarker");
AddComponent(staticRootMarker, new BakeStaticRoot() { Body = bodyEntity, ConvertedBodyInstanceID = body.transform.GetInstanceID() });
}
// Track dependencies to the transforms
Transform shapeTransform = GetComponent<Transform>(shape);
Transform bodyTransform = GetComponent<Transform>(body);
var instance = new ColliderInstanceBaking
{
AuthoringComponentId = shapeInstanceID,
BodyEntity = bodyEntity,
ShapeEntity = GetEntity(shapeGameObject, TransformUsageFlags.Dynamic),
ChildEntity = GetEntity(child, TransformUsageFlags.Dynamic),
BodyFromShape = ColliderInstanceBaking.GetCompoundFromChild(shapeTransform, bodyTransform),
};
ForceUniqueColliderAuthoring forceUniqueComponent = body.GetComponent<ForceUniqueColliderAuthoring>();
bool isForceUniqueComponentPresent = forceUniqueComponent != null;
var data = GenerateComputationData(shape, bodyTransform, instance, colliderEntity, isForceUniqueComponentPresent);
data.Instance.ConvertedAuthoringInstanceID = shapeInstanceID;
data.Instance.ConvertedBodyInstanceID = bodyTransform.GetInstanceID();
var rb = FindFirstEnabledAncestor(shapeGameObject, PhysicsShapeExtensions_NonBursted.s_RigidbodiesBuffer);
var pb = FindFirstEnabledAncestor(shapeGameObject, PhysicsShapeExtensions_NonBursted.s_PhysicsBodiesBuffer);
// The Rigidbody cannot know about the Physics Shape Component. We need to take responsibility of baking the collider.
if (rb || (!rb && !pb) && body == shapeGameObject)
{
GetComponents(physicsShapeComponents);
GetComponents(colliderComponents);
// We need to check that there are no other colliders in the same object, if so, only the first one should do this, otherwise there will be 2 bakers adding this to the entity
// This will be needed to trigger BuildCompoundColliderBakingSystem
// If they are legacy Colliders and PhysicsShapeAuthoring in the same object, the PhysicsShapeAuthoring will add this
if (colliderComponents.Count == 0 && physicsShapeComponents.Count > 0 && physicsShapeComponents[0].GetInstanceID() == shapeInstanceID)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
// // Rigid Body bakes always add the PhysicsWorldIndex component and process transform
if (!hasBodyComponent)
{
AddSharedComponent(entity, new PhysicsWorldIndex());
PostProcessTransform(bodyTransform);
}
AddComponent(entity, new PhysicsCompoundData()
{
AssociateBlobToBody = false,
ConvertedBodyInstanceID = shapeInstanceID,
Hash = default,
});
AddComponent<PhysicsRootBaked>(entity);
AddComponent<PhysicsCollider>(entity);
}
}
return data;
}
Material ProduceMaterial(PhysicsShapeAuthoring shape)
{
var materialTemplate = shape.MaterialTemplate;
if (materialTemplate != null)
DependsOn(materialTemplate);
return shape.GetMaterial();
}
CollisionFilter ProduceCollisionFilter(PhysicsShapeAuthoring shape)
{
return shape.GetFilter();
}
UnityEngine.Mesh GetMesh(PhysicsShapeAuthoring shape, out float4x4 childToShape)
{
var mesh = shape.CustomMesh;
childToShape = float4x4.identity;
if (mesh == null)
{
// Try to get a mesh in the children
var filter = GetComponentInChildren<MeshFilter>();
if (filter != null && filter.sharedMesh != null)
{
mesh = filter.sharedMesh;
var childTransform = GetComponent<Transform>(filter);
childToShape = math.mul(shape.transform.worldToLocalMatrix, childTransform.localToWorldMatrix);;
}
}
if (mesh == null)
{
throw new InvalidOperationException(
$"No {nameof(PhysicsShapeAuthoring.CustomMesh)} assigned on {shape.name}."
);
}
DependsOn(mesh);
return mesh;
}
bool GetMeshes(PhysicsShapeAuthoring shape, out List<UnityEngine.Mesh> meshes, out List<float4x4> childrenToShape)
{
meshes = new List<UnityEngine.Mesh>();
childrenToShape = new List<float4x4>();
if (shape.CustomMesh != null)
{
meshes.Add(shape.CustomMesh);
childrenToShape.Add(float4x4.identity);
}
else
{
// Try to get all the meshes in the children
var meshFilters = GetComponentsInChildren<MeshFilter>();
foreach (var meshFilter in meshFilters)
{
if (meshFilter != null && meshFilter.sharedMesh != null)
{
var shapeAuthoring = GetComponent<PhysicsShapeAuthoring>(meshFilter);
if (shapeAuthoring != null && shapeAuthoring != shape)
{
// Skip this case, since it will be treated independently
continue;
}
meshes.Add(meshFilter.sharedMesh);
// Don't calculate the children to shape if not needed, to avoid approximation that could prevent collider to be shared
if (shape.transform.localToWorldMatrix.Equals(meshFilter.transform.localToWorldMatrix))
childrenToShape.Add(float4x4.identity);
else
{
var transform = math.mul(shape.transform.worldToLocalMatrix,
meshFilter.transform.localToWorldMatrix);
childrenToShape.Add(transform);
}
DependsOn(meshes.Last());
}
}
}
return meshes.Count > 0;
}
UnityEngine.Mesh CombineMeshes(PhysicsShapeAuthoring shape, List<UnityEngine.Mesh> meshes, List<float4x4> childrenToShape)
{
var instances = new List<CombineInstance>();
var numVertices = 0;
for (var i = 0; i < meshes.Count; ++i)
{
var currentMesh = meshes[i];
var currentChildToShape = childrenToShape[i];
if (!currentMesh.IsValidForConversion(shape.gameObject))
{
throw new InvalidOperationException(
$"Mesh '{currentMesh}' assigned on {shape.name} is not readable. Ensure that you have enabled Read/Write on its import settings."
);
}
// Combine submeshes manually
numVertices += meshes[i].vertexCount;
var combinedSubmeshes = new UnityEngine.Mesh();
combinedSubmeshes.vertices = currentMesh.vertices;
var combinedIndices = new List<int>();
for (int indexSubMesh = 0; indexSubMesh < meshes[i].subMeshCount; ++indexSubMesh)
{
combinedIndices.AddRange(currentMesh.GetIndices(indexSubMesh));
}
combinedSubmeshes.SetIndices(combinedIndices, MeshTopology.Triangles, 0);
combinedSubmeshes.RecalculateNormals();
var instance = new CombineInstance
{
mesh = combinedSubmeshes,
transform = currentChildToShape,
};
instances.Add(instance);
}
var mesh = new UnityEngine.Mesh();
mesh.indexFormat = numVertices > UInt16.MaxValue ? UnityEngine.Rendering.IndexFormat.UInt32 : UnityEngine.Rendering.IndexFormat.UInt16;
mesh.CombineMeshes(instances.ToArray());
mesh.RecalculateBounds();
return mesh;
}
private ShapeComputationDataBaking GenerateComputationData(PhysicsShapeAuthoring shape, Transform bodyTransform, ColliderInstanceBaking colliderInstance, Entity colliderEntity, bool isForceUniqueComponentPresent)
{
bool isUnique = isForceUniqueComponentPresent || shape.ForceUnique;
var res = new ShapeComputationDataBaking
{
Instance = colliderInstance,
Material = ProduceMaterial(shape),
CollisionFilter = ProduceCollisionFilter(shape),
ForceUniqueIdentifier = isUnique ? (uint)shape.GetInstanceID() : 0u
};
var shapeTransform = shape.transform;
var localToWorld = (float4x4)shapeTransform.localToWorldMatrix;
var bodyLocalToWorld = (float4x4)bodyTransform.transform.localToWorldMatrix;
// We don't bake pure uniform scales into colliders since edit-time uniform scales
// are baked into the entity's LocalTransform.Scale property, unless the shape has non-identity scale
// relative to its contained body. In this case we need to bake all scales into the collider geometry.
var relativeTransform = math.mul(math.inverse(bodyLocalToWorld), localToWorld);
var hasNonIdentityScaleRelativeToBody = relativeTransform.HasNonIdentityScale();
var hasShearRelativeToBody = relativeTransform.HasShear();
var bakeUniformScale = hasNonIdentityScaleRelativeToBody || hasShearRelativeToBody;
// If the body transform has purely uniform scale, and there is any scale or shear between the body and the shape,
// then we need to extract the uniform body scale from the shape transform before baking
// to prevent the shape from being scaled by the body's uniform scale twice. This is because pure top level body uniform scales
// are not baked into collider geometry but represented by the body entity's LocalTransform.Scale property.
if (bakeUniformScale)
{
var bodyHasShear = bodyLocalToWorld.HasShear();
var bodyHasNonUniformScale = bodyLocalToWorld.HasNonUniformScale();
if (!bodyHasShear && !bodyHasNonUniformScale)
{
// extract uniform scale of body and remove it from the shape transform
var bodyScale = bodyLocalToWorld.DecomposeScale();
var bodyScaleInverse = 1 / bodyScale;
localToWorld = math.mul(localToWorld, float4x4.Scale(bodyScaleInverse));
}
}
// bake uniform scale only if required (see above), and always bake shear and non-uniform scales into the collider geometry
var colliderBakeMatrix = float4x4.identity;
if (bakeUniformScale || localToWorld.HasShear() || localToWorld.HasNonUniformScale())
{
var rigidBodyTransform = Math.DecomposeRigidBodyTransform(localToWorld);
colliderBakeMatrix = math.mul(math.inverse(new float4x4(rigidBodyTransform)), localToWorld);
// make sure we have a valid transformation matrix
colliderBakeMatrix.c0[3] = 0;
colliderBakeMatrix.c1[3] = 0;
colliderBakeMatrix.c2[3] = 0;
colliderBakeMatrix.c3[3] = 1;
}
var shapeToWorld = shape.GetShapeToWorldMatrix();
EulerAngles orientation;
res.ShapeType = shape.ShapeType;
switch (shape.ShapeType)
{
case ShapeType.Box:
{
res.BoxProperties = shape.GetBoxProperties(out orientation)
.BakeToBodySpace(localToWorld, shapeToWorld, orientation, bakeUniformScale);
break;
}
case ShapeType.Capsule:
{
res.CapsuleProperties = shape.GetCapsuleProperties()
.BakeToBodySpace(localToWorld, shapeToWorld, bakeUniformScale)
.ToRuntime();
break;
}
case ShapeType.Sphere:
{
res.SphereProperties = shape.GetSphereProperties(out orientation)
.BakeToBodySpace(localToWorld, shapeToWorld, ref orientation, bakeUniformScale);
break;
}
case ShapeType.Cylinder:
{
res.CylinderProperties = shape.GetCylinderProperties(out orientation)
.BakeToBodySpace(localToWorld, shapeToWorld, orientation, bakeUniformScale);
break;
}
case ShapeType.Plane:
{
shape.GetPlaneProperties(out var center, out var size, out orientation);
PhysicsShapeExtensions.BakeToBodySpace(
center, size, orientation, colliderBakeMatrix,
out res.PlaneVertices.c0, out res.PlaneVertices.c1, out res.PlaneVertices.c2, out res.PlaneVertices.c3
);
break;
}
case ShapeType.ConvexHull:
{
res.ConvexHullProperties.Filter = res.CollisionFilter;
res.ConvexHullProperties.Material = res.Material;
res.ConvexHullProperties.GenerationParameters = shape.ConvexHullGenerationParameters.ToRunTime();
CreateMeshAuthoringData(shape, colliderBakeMatrix, colliderEntity);
break;
}
case ShapeType.Mesh:
{
res.MeshProperties.Filter = res.CollisionFilter;
res.MeshProperties.Material = res.Material;
CreateMeshAuthoringData(shape, colliderBakeMatrix, colliderEntity);
break;
}
}
return res;
}
private void CreateMeshAuthoringData(PhysicsShapeAuthoring shape, float4x4 colliderBakeMatrix, Entity colliderEntity)
{
if (GetMeshes(shape, out var meshes, out var childrenToShape))
{
// Combine all detected meshes into a single one
var mesh = CombineMeshes(shape, meshes, childrenToShape);
if (!mesh.IsValidForConversion(shape.gameObject))
{
throw new InvalidOperationException(
$"Mesh '{mesh}' assigned on {shape.name} is not readable. Ensure that you have enabled Read/Write on its import settings."
);
}
var meshBakingData = new PhysicsMeshAuthoringData()
{
Convex = shape.ShapeType == ShapeType.ConvexHull,
Mesh = mesh,
BakeFromShape = colliderBakeMatrix,
MeshBounds = mesh.bounds,
ChildToShape = float4x4.identity
};
AddComponent(colliderEntity, meshBakingData);
}
else
{
throw new InvalidOperationException(
$"No {nameof(PhysicsShapeAuthoring.CustomMesh)} or {nameof(MeshFilter.sharedMesh)} assigned on {shape.name}."
);
}
}
public override void Bake(PhysicsShapeAuthoring authoring)
{
var shapeBakingData = new PhysicsColliderAuthoringData();
// First pass
Profiler.BeginSample("Collect Inputs from Authoring Components");
if (ShouldConvertShape(authoring))
{
// We can have multiple Colliders of the same type on the same game object, so instead of adding the components to the baking entity
// we add the components to an additional entity. These new entities will be processed by the baking system
var colliderEntity = CreateAdditionalEntity(TransformUsageFlags.None, true);
shapeBakingData.ShapeComputationalData = GetInputDataFromAuthoringComponent(authoring, colliderEntity);
AddComponent(colliderEntity, shapeBakingData);
// The data will be filled in by the BaseShapeBakingSystem, but we add it here so it gets reverted from the entity if the collider component is deleted
AddComponent(colliderEntity, new PhysicsColliderBakedData()
{
BodyEntity = shapeBakingData.ShapeComputationalData.Instance.BodyEntity,
BodyFromShape = shapeBakingData.ShapeComputationalData.Instance.BodyFromShape,
ChildEntity = shapeBakingData.ShapeComputationalData.Instance.ChildEntity,
// It is a leaf if the Shape Entity equals Body Entity
IsLeafEntityBody = (shapeBakingData.ShapeComputationalData.Instance.ShapeEntity.Equals(shapeBakingData.ShapeComputationalData.Instance.BodyEntity))
});
}
Profiler.EndSample();
}
}
}
fileFormatVersion: 2
guid: c7b2bb3849ee2c24ea6f8416bc3c8ee0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
/// <summary> The physics body authoring. This class cannot be inherited. </summary>
#if UNITY_2021_2_OR_NEWER
[Icon(k_IconPath)]
#endif
[AddComponentMenu("Entities/Physics/Physics Body")]
[DisallowMultipleComponent]
public sealed class PhysicsBodyAuthoring : MonoBehaviour
{
const string k_IconPath = "Packages/com.unity.physics/Unity.Physics.Editor/Editor Default Resources/Icons/d_Rigidbody@64.png";
PhysicsBodyAuthoring() {}
public BodyMotionType MotionType { get => m_MotionType; set => m_MotionType = value; }
[SerializeField]
[Tooltip("Specifies whether the body should be fully physically simulated, moved directly, or fixed in place.")]
BodyMotionType m_MotionType;
public BodySmoothing Smoothing { get => m_Smoothing; set => m_Smoothing = value; }
[SerializeField]
[Tooltip("Specifies how this body's motion in its graphics representation should be smoothed when the rendering framerate is greater than the fixed step rate used by physics.")]
BodySmoothing m_Smoothing = BodySmoothing.None;
const float k_MinimumMass = 0.001f;
public float Mass
{
get => m_MotionType == BodyMotionType.Dynamic ? m_Mass : float.PositiveInfinity;
set => m_Mass = math.max(k_MinimumMass, value);
}
[SerializeField]
float m_Mass = 1.0f;
public float LinearDamping { get => m_LinearDamping; set => m_LinearDamping = math.max(0f, value); }
[SerializeField]
[Tooltip("This is applied to a body's linear velocity reducing it over time.")]
float m_LinearDamping = 0.01f;
public float AngularDamping { get => m_AngularDamping; set => m_AngularDamping = math.max(0f, value); }
[SerializeField]
[Tooltip("This is applied to a body's angular velocity reducing it over time.")]
float m_AngularDamping = 0.05f;
public float3 InitialLinearVelocity { get => m_InitialLinearVelocity; set => m_InitialLinearVelocity = value; }
[SerializeField]
[Tooltip("The initial linear velocity of the body in world space")]
float3 m_InitialLinearVelocity = float3.zero;
public float3 InitialAngularVelocity { get => m_InitialAngularVelocity; set => m_InitialAngularVelocity = value; }
[SerializeField]
[Tooltip("This represents the initial rotation speed around each axis in the local motion space of the body i.e. around the center of mass")]
float3 m_InitialAngularVelocity = float3.zero;
public float GravityFactor
{
get => m_MotionType == BodyMotionType.Dynamic ? m_GravityFactor : 0f;
set => m_GravityFactor = value;
}
[SerializeField]
[Tooltip("Scales the amount of gravity to apply to this body.")]
float m_GravityFactor = 1f;
public bool OverrideDefaultMassDistribution
{
#pragma warning disable 618
get => m_OverrideDefaultMassDistribution;
set => m_OverrideDefaultMassDistribution = value;
#pragma warning restore 618
}
[SerializeField]
[Tooltip("Override default mass distribution based on the shapes associated with this body by the specified mass distribution, assuming unit mass.")]
bool m_OverrideDefaultMassDistribution;
public MassDistribution CustomMassDistribution
{
get => new MassDistribution
{
Transform = new RigidTransform(m_Orientation, m_CenterOfMass),
InertiaTensor =
m_MotionType == BodyMotionType.Dynamic ? m_InertiaTensor : new float3(float.PositiveInfinity)
};
set
{
m_CenterOfMass = value.Transform.pos;
m_Orientation.SetValue(value.Transform.rot);
m_InertiaTensor = value.InertiaTensor;
#pragma warning disable 618
m_OverrideDefaultMassDistribution = true;
#pragma warning restore 618
}
}
[SerializeField]
float3 m_CenterOfMass;
[SerializeField]
EulerAngles m_Orientation = EulerAngles.Default;
[SerializeField]
// Default value to solid unit sphere : https://en.wikipedia.org/wiki/List_of_moments_of_inertia
float3 m_InertiaTensor = new float3(2f / 5f);
public uint WorldIndex { get => m_WorldIndex; set => m_WorldIndex = value; }
[SerializeField]
[Tooltip("The index of the physics world this body belongs to. Default physics world has index 0.")]
uint m_WorldIndex = 0;
public CustomPhysicsBodyTags CustomTags { get => m_CustomTags; set => m_CustomTags = value; }
[SerializeField]
CustomPhysicsBodyTags m_CustomTags = CustomPhysicsBodyTags.Nothing;
void OnEnable()
{
// included so tick box appears in Editor
}
void OnValidate()
{
m_Mass = math.max(k_MinimumMass, m_Mass);
m_LinearDamping = math.max(m_LinearDamping, 0f);
m_AngularDamping = math.max(m_AngularDamping, 0f);
}
}
}
fileFormatVersion: 2
guid: ccea9ea98e38942e0b0938c27ed1903e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering;
namespace Unity.Physics.Authoring
{
public sealed class UnimplementedShapeException : NotImplementedException
{
public UnimplementedShapeException(ShapeType shapeType)
: base($"Unknown shape type {shapeType} requires explicit implementation") {}
}
#if UNITY_2021_2_OR_NEWER
[Icon(k_IconPath)]
#endif
[AddComponentMenu("Entities/Physics/Physics Shape")]
public sealed class PhysicsShapeAuthoring : MonoBehaviour, IInheritPhysicsMaterialProperties, ISerializationCallbackReceiver
{
const string k_IconPath = "Packages/com.unity.physics/Unity.Physics.Editor/Editor Default Resources/Icons/d_BoxCollider@64.png";
PhysicsShapeAuthoring() {}
[Serializable]
struct CylindricalProperties
{
public float Height;
public float Radius;
[HideInInspector]
public int Axis;
}
static readonly int[] k_NextAxis = { 1, 2, 0 };
public ShapeType ShapeType => m_ShapeType;
[SerializeField]
ShapeType m_ShapeType = ShapeType.Box;
[SerializeField]
float3 m_PrimitiveCenter;
[SerializeField]
float3 m_PrimitiveSize = new float3(1f, 1f, 1f);
[SerializeField]
EulerAngles m_PrimitiveOrientation = EulerAngles.Default;
[SerializeField]
[ExpandChildren]
CylindricalProperties m_Capsule = new CylindricalProperties { Height = 1f, Radius = 0.5f, Axis = 2 };
[SerializeField]
[ExpandChildren]
CylindricalProperties m_Cylinder = new CylindricalProperties { Height = 1f, Radius = 0.5f, Axis = 2 };
[SerializeField]
[Tooltip("How many sides the convex cylinder shape should have.")]
[Range(CylinderGeometry.MinSideCount, CylinderGeometry.MaxSideCount)]
int m_CylinderSideCount = 20;
[SerializeField]
float m_SphereRadius = 0.5f;
public ConvexHullGenerationParameters ConvexHullGenerationParameters => m_ConvexHullGenerationParameters;
[SerializeField]
[Tooltip(
"Specifies the minimum weight of a skinned vertex assigned to this shape and/or its transform children required for it to be included for automatic detection. " +
"A value of 0 will include all points with any weight assigned to this shape's hierarchy."
)]
[Range(0f, 1f)]
float m_MinimumSkinnedVertexWeight = 0.1f;
[SerializeField]
[ExpandChildren]
ConvexHullGenerationParameters m_ConvexHullGenerationParameters = ConvexHullGenerationParameters.Default.ToAuthoring();
// TODO: remove this accessor in favor of GetRawVertices() when blob data is serializable
internal UnityEngine.Mesh CustomMesh => m_CustomMesh;
[SerializeField]
[Tooltip("If no custom mesh is specified, then one will be generated using this body's rendered meshes.")]
UnityEngine.Mesh m_CustomMesh;
public bool ForceUnique { get => m_ForceUnique; set => m_ForceUnique = value; }
[SerializeField]
bool m_ForceUnique;
public PhysicsMaterialTemplate MaterialTemplate { get => m_Material.Template; set => m_Material.Template = value; }
PhysicsMaterialTemplate IInheritPhysicsMaterialProperties.Template
{
get => m_Material.Template;
set => m_Material.Template = value;
}
public bool OverrideCollisionResponse { get => m_Material.OverrideCollisionResponse; set => m_Material.OverrideCollisionResponse = value; }
public CollisionResponsePolicy CollisionResponse { get => m_Material.CollisionResponse; set => m_Material.CollisionResponse = value; }
public bool OverrideFriction { get => m_Material.OverrideFriction; set => m_Material.OverrideFriction = value; }
public PhysicsMaterialCoefficient Friction { get => m_Material.Friction; set => m_Material.Friction = value; }
public bool OverrideRestitution
{
get => m_Material.OverrideRestitution;
set => m_Material.OverrideRestitution = value;
}
public PhysicsMaterialCoefficient Restitution
{
get => m_Material.Restitution;
set => m_Material.Restitution = value;
}
public bool OverrideBelongsTo
{
get => m_Material.OverrideBelongsTo;
set => m_Material.OverrideBelongsTo = value;
}
public PhysicsCategoryTags BelongsTo
{
get => m_Material.BelongsTo;
set => m_Material.BelongsTo = value;
}
public bool OverrideCollidesWith
{
get => m_Material.OverrideCollidesWith;
set => m_Material.OverrideCollidesWith = value;
}
public PhysicsCategoryTags CollidesWith
{
get => m_Material.CollidesWith;
set => m_Material.CollidesWith = value;
}
public bool OverrideCustomTags
{
get => m_Material.OverrideCustomTags;
set => m_Material.OverrideCustomTags = value;
}
public CustomPhysicsMaterialTags CustomTags { get => m_Material.CustomTags; set => m_Material.CustomTags = value; }
[SerializeField]
PhysicsMaterialProperties m_Material = new PhysicsMaterialProperties(true);
public BoxGeometry GetBoxProperties() => GetBoxProperties(out _);
internal BoxGeometry GetBoxProperties(out EulerAngles orientation)
{
orientation = m_PrimitiveOrientation;
return new BoxGeometry
{
Center = m_PrimitiveCenter,
Size = m_PrimitiveSize,
Orientation = m_PrimitiveOrientation,
BevelRadius = m_ConvexHullGenerationParameters.BevelRadius
};
}
void GetCylindricalProperties(
CylindricalProperties props,
out float3 center, out float height, out float radius, out EulerAngles orientation,
bool rebuildOrientation
)
{
center = m_PrimitiveCenter;
var lookVector = math.mul(m_PrimitiveOrientation, new float3 { [props.Axis] = 1f });
// use previous axis so forward will prefer up
var upVector = math.mul(m_PrimitiveOrientation, new float3 { [k_NextAxis[k_NextAxis[props.Axis]]] = 1f });
orientation = m_PrimitiveOrientation;
if (rebuildOrientation && props.Axis != 2)
orientation.SetValue(quaternion.LookRotation(lookVector, upVector));
radius = props.Radius;
height = props.Height;
}
public CapsuleGeometryAuthoring GetCapsuleProperties()
{
GetCylindricalProperties(
m_Capsule, out var center, out var height, out var radius, out var orientationEuler, m_ShapeType != ShapeType.Capsule
);
return new CapsuleGeometryAuthoring
{
OrientationEuler = orientationEuler,
Center = center,
Height = height,
Radius = radius
};
}
public CylinderGeometry GetCylinderProperties() => GetCylinderProperties(out _);
internal CylinderGeometry GetCylinderProperties(out EulerAngles orientation)
{
GetCylindricalProperties(
m_Cylinder, out var center, out var height, out var radius, out orientation, m_ShapeType != ShapeType.Cylinder
);
return new CylinderGeometry
{
Center = center,
Height = height,
Radius = radius,
Orientation = orientation,
BevelRadius = m_ConvexHullGenerationParameters.BevelRadius,
SideCount = m_CylinderSideCount
};
}
public SphereGeometry GetSphereProperties(out quaternion orientation)
{
var result = GetSphereProperties(out EulerAngles euler);
orientation = euler;
return result;
}
internal SphereGeometry GetSphereProperties(out EulerAngles orientation)
{
orientation = m_PrimitiveOrientation;
return new SphereGeometry
{
Center = m_PrimitiveCenter,
Radius = m_SphereRadius
};
}
public void GetPlaneProperties(out float3 center, out float2 size, out quaternion orientation)
{
GetPlaneProperties(out center, out size, out EulerAngles euler);
orientation = euler;
}
internal void GetPlaneProperties(out float3 center, out float2 size, out EulerAngles orientation)
{
center = m_PrimitiveCenter;
orientation = m_PrimitiveOrientation;
if (m_ShapeType == ShapeType.Plane)
{
size = m_PrimitiveSize.xz;
return;
}
UpdateCapsuleAxis();
var look = m_Capsule.Axis;
var nextAx = k_NextAxis[look];
var prevAx = k_NextAxis[k_NextAxis[look]];
var ax2 = m_PrimitiveSize[nextAx] > m_PrimitiveSize[prevAx] ? nextAx : prevAx;
size = new float2(m_PrimitiveSize[ax2], m_PrimitiveSize[look]);
var up = k_NextAxis[ax2] == look ? k_NextAxis[look] : k_NextAxis[ax2];
var offset = quaternion.LookRotation(new float3 { [look] = 1f }, new float3 { [up] = 1f });
orientation.SetValue(math.mul(m_PrimitiveOrientation, offset));
}
static readonly HashSet<int> s_BoneIDs = new HashSet<int>();
static readonly HashSet<Transform> s_BonesInHierarchy = new HashSet<Transform>();
static readonly List<Vector3> s_Vertices = new List<Vector3>(65535);
static readonly List<int> s_Indices = new List<int>(65535);
static UnityEngine.Mesh ReusableBakeMesh =>
s_ReusableBakeMesh ??
(s_ReusableBakeMesh = new UnityEngine.Mesh { hideFlags = HideFlags.HideAndDontSave });
static UnityEngine.Mesh s_ReusableBakeMesh;
public void GetConvexHullProperties(NativeList<float3> pointCloud) =>
GetConvexHullProperties(pointCloud, true, default, default, default, default);
internal void GetConvexHullProperties(
NativeList<float3> pointCloud, bool validate,
NativeList<HashableShapeInputs> inputs, NativeList<int> allSkinIndices, NativeList<float> allBlendShapeWeights,
HashSet<UnityEngine.Mesh> meshAssets
)
{
if (pointCloud.IsCreated)
pointCloud.Clear();
if (inputs.IsCreated)
inputs.Clear();
if (allSkinIndices.IsCreated)
allSkinIndices.Clear();
if (allBlendShapeWeights.IsCreated)
allBlendShapeWeights.Clear();
meshAssets?.Clear();
if (m_CustomMesh != null)
{
if (validate && !m_CustomMesh.IsValidForConversion(gameObject))
return;
AppendMeshPropertiesToNativeBuffers(
transform.localToWorldMatrix, m_CustomMesh, pointCloud, default, validate, inputs, meshAssets
);
}
else
{
using (var scope = new GetActiveChildrenScope<MeshFilter>(this, transform))
{
foreach (var meshFilter in scope.Buffer)
{
if (scope.IsChildActiveAndBelongsToShape(meshFilter, validate))
{
AppendMeshPropertiesToNativeBuffers(
meshFilter.transform.localToWorldMatrix, meshFilter.sharedMesh, pointCloud, default, validate, inputs, meshAssets
);
}
}
}
using (var skinnedPoints = new NativeList<float3>(8192, Allocator.Temp))
using (var skinnedInputs = new NativeList<HashableShapeInputs>(8, Allocator.Temp))
{
GetAllSkinnedPointsInHierarchyBelongingToShape(
this, skinnedPoints, validate, skinnedInputs, allSkinIndices, allBlendShapeWeights
);
if (pointCloud.IsCreated)
pointCloud.AddRange(skinnedPoints.AsArray());
if (inputs.IsCreated)
inputs.AddRange(skinnedInputs.AsArray());
}
}
}
internal static void GetAllSkinnedPointsInHierarchyBelongingToShape(
PhysicsShapeAuthoring shape, NativeList<float3> pointCloud, bool validate,
NativeList<HashableShapeInputs> inputs, NativeList<int> allIncludedIndices, NativeList<float> allBlendShapeWeights
)
{
if (pointCloud.IsCreated)
pointCloud.Clear();
if (inputs.IsCreated)
inputs.Clear();
// get all the transforms that belong to this shape
s_BonesInHierarchy.Clear();
using (var scope = new GetActiveChildrenScope<Transform>(shape, shape.transform))
{
foreach (var bone in scope.Buffer)
{
if (scope.IsChildActiveAndBelongsToShape(bone))
s_BonesInHierarchy.Add(bone);
}
}
// find all skinned mesh renderers in which this shape's transform might be a bone
using (var scope = new GetActiveChildrenScope<SkinnedMeshRenderer>(shape, shape.transform.root))
{
foreach (var skin in scope.Buffer)
{
var mesh = skin.sharedMesh;
if (
!skin.enabled
|| mesh == null
|| validate && !mesh.IsValidForConversion(shape.gameObject)
|| !scope.IsChildActiveAndBelongsToShape(skin)
)
continue;
// get indices of this shape's transform hierarchy in skinned mesh's bone array
s_BoneIDs.Clear();
var bones = skin.bones;
for (int i = 0, count = bones.Length; i < count; ++i)
{
if (s_BonesInHierarchy.Contains(bones[i]))
s_BoneIDs.Add(i);
}
if (s_BoneIDs.Count == 0)
continue;
// sample the vertices
if (pointCloud.IsCreated)
{
skin.BakeMesh(ReusableBakeMesh);
ReusableBakeMesh.GetVertices(s_Vertices);
}
// add all vertices weighted to at least one bone in this shape's transform hierarchy
var bonesPerVertex = mesh.GetBonesPerVertex(); // Allocator.None
var weights = mesh.GetAllBoneWeights(); // Allocator.None
var vertexIndex = 0;
var weightsOffset = 0;
var shapeFromSkin = math.mul(shape.transform.worldToLocalMatrix, skin.transform.localToWorldMatrix);
var includedIndices = new NativeList<int>(mesh.vertexCount, Allocator.Temp);
foreach (var weightCount in bonesPerVertex)
{
var totalWeight = 0f;
for (var i = 0; i < weightCount; ++i)
{
var weight = weights[weightsOffset + i];
if (s_BoneIDs.Contains(weight.boneIndex))
totalWeight += weight.weight;
}
if (totalWeight > shape.m_MinimumSkinnedVertexWeight)
{
if (pointCloud.IsCreated)
pointCloud.Add(math.mul(shapeFromSkin, new float4(s_Vertices[vertexIndex], 1f)).xyz);
includedIndices.Add(vertexIndex);
}
weightsOffset += weightCount;
++vertexIndex;
}
if (!inputs.IsCreated || !allIncludedIndices.IsCreated || !allBlendShapeWeights.IsCreated)
continue;
var blendShapeWeights = new NativeArray<float>(mesh.blendShapeCount, Allocator.Temp);
for (var i = 0; i < blendShapeWeights.Length; ++i)
blendShapeWeights[i] = skin.GetBlendShapeWeight(i);
var data = HashableShapeInputs.FromSkinnedMesh(
mesh, shapeFromSkin, includedIndices.AsArray(), allIncludedIndices, blendShapeWeights, allBlendShapeWeights
);
inputs.Add(data);
}
}
s_BonesInHierarchy.Clear();
}
public void GetMeshProperties(NativeList<float3> vertices, NativeList<int3> triangles) =>
GetMeshProperties(vertices, triangles, true, default);
internal void GetMeshProperties(
NativeList<float3> vertices, NativeList<int3> triangles, bool validate, NativeList<HashableShapeInputs> inputs, HashSet<UnityEngine.Mesh> meshAssets = null
)
{
if (vertices.IsCreated)
vertices.Clear();
if (triangles.IsCreated)
triangles.Clear();
if (inputs.IsCreated)
inputs.Clear();
meshAssets?.Clear();
if (m_CustomMesh != null)
{
if (validate && !m_CustomMesh.IsValidForConversion(gameObject))
return;
AppendMeshPropertiesToNativeBuffers(
transform.localToWorldMatrix, m_CustomMesh, vertices, triangles, validate, inputs, meshAssets
);
}
else
{
using (var scope = new GetActiveChildrenScope<MeshFilter>(this, transform))
{
foreach (var meshFilter in scope.Buffer)
{
if (scope.IsChildActiveAndBelongsToShape(meshFilter, validate))
{
AppendMeshPropertiesToNativeBuffers(
meshFilter.transform.localToWorldMatrix, meshFilter.sharedMesh, vertices, triangles, validate, inputs, meshAssets
);
}
}
}
}
}
void AppendMeshPropertiesToNativeBuffers(
float4x4 localToWorld, UnityEngine.Mesh mesh, NativeList<float3> vertices, NativeList<int3> triangles, bool validate,
NativeList<HashableShapeInputs> inputs, HashSet<UnityEngine.Mesh> meshAssets
)
{
if (mesh == null || validate && !mesh.IsValidForConversion(gameObject))
return;
var childToShape = math.mul(transform.worldToLocalMatrix, localToWorld);
AppendMeshPropertiesToNativeBuffers(childToShape, mesh, vertices, triangles, inputs, meshAssets);
}
internal static void AppendMeshPropertiesToNativeBuffers(
float4x4 childToShape, UnityEngine.Mesh mesh, NativeList<float3> vertices, NativeList<int3> triangles,
NativeList<HashableShapeInputs> inputs, HashSet<UnityEngine.Mesh> meshAssets
)
{
var offset = 0u;
#if UNITY_EDITOR
// TODO: when min spec is 2020.1, collect all meshes and their data via single Burst job rather than one at a time
using (var meshData = UnityEditor.MeshUtility.AcquireReadOnlyMeshData(mesh))
#else
using (var meshData = UnityEngine.Mesh.AcquireReadOnlyMeshData(mesh))
#endif
{
if (vertices.IsCreated)
{
offset = (uint)vertices.Length;
var tmpVertices = new NativeArray<Vector3>(meshData[0].vertexCount, Allocator.Temp);
meshData[0].GetVertices(tmpVertices);
if (vertices.Capacity < vertices.Length + tmpVertices.Length)
vertices.Capacity = vertices.Length + tmpVertices.Length;
foreach (var v in tmpVertices)
vertices.Add(math.mul(childToShape, new float4(v, 1f)).xyz);
}
if (triangles.IsCreated)
{
switch (meshData[0].indexFormat)
{
case IndexFormat.UInt16:
var indices16 = meshData[0].GetIndexData<ushort>();
var numTriangles = indices16.Length / 3;
if (triangles.Capacity < triangles.Length + numTriangles)
triangles.Capacity = triangles.Length + numTriangles;
for (var sm = 0; sm < meshData[0].subMeshCount; ++sm)
{
var subMesh = meshData[0].GetSubMesh(sm);
for (int i = subMesh.indexStart, count = 0; count < subMesh.indexCount; i += 3, count += 3)
triangles.Add((int3) new uint3(offset + indices16[i], offset + indices16[i + 1], offset + indices16[i + 2]));
}
break;
case IndexFormat.UInt32:
var indices32 = meshData[0].GetIndexData<uint>();
numTriangles = indices32.Length / 3;
if (triangles.Capacity < triangles.Length + numTriangles)
triangles.Capacity = triangles.Length + numTriangles;
for (var sm = 0; sm < meshData[0].subMeshCount; ++sm)
{
var subMesh = meshData[0].GetSubMesh(sm);
for (int i = subMesh.indexStart, count = 0; count < subMesh.indexCount; i += 3, count += 3)
triangles.Add((int3) new uint3(offset + indices32[i], offset + indices32[i + 1], offset + indices32[i + 2]));
}
break;
}
}
}
if (inputs.IsCreated)
inputs.Add(HashableShapeInputs.FromMesh(mesh, childToShape));
meshAssets?.Add(mesh);
}
void UpdateCapsuleAxis()
{
var cmax = math.cmax(m_PrimitiveSize);
var cmin = math.cmin(m_PrimitiveSize);
if (cmin == cmax)
return;
m_Capsule.Axis = m_PrimitiveSize.GetMaxAxis();
}
void UpdateCylinderAxis() => m_Cylinder.Axis = m_PrimitiveSize.GetDeviantAxis();
void Sync(ref CylindricalProperties props)
{
props.Height = m_PrimitiveSize[props.Axis];
props.Radius = 0.5f * math.max(
m_PrimitiveSize[k_NextAxis[props.Axis]],
m_PrimitiveSize[k_NextAxis[k_NextAxis[props.Axis]]]
);
}
void SyncCapsuleProperties()
{
if (m_ShapeType == ShapeType.Box || m_ShapeType == ShapeType.Plane)
UpdateCapsuleAxis();
else
m_Capsule.Axis = 2;
Sync(ref m_Capsule);
}
void SyncCylinderProperties()
{
if (m_ShapeType == ShapeType.Box || m_ShapeType == ShapeType.Plane)
UpdateCylinderAxis();
else
m_Cylinder.Axis = 2;
Sync(ref m_Cylinder);
}
void SyncSphereProperties()
{
m_SphereRadius = 0.5f * math.cmax(m_PrimitiveSize);
}
public void SetBox(BoxGeometry geometry)
{
var euler = m_PrimitiveOrientation;
euler.SetValue(geometry.Orientation);
SetBox(geometry, euler);
}
internal void SetBox(BoxGeometry geometry, EulerAngles orientation)
{
m_ShapeType = ShapeType.Box;
m_PrimitiveCenter = geometry.Center;
m_PrimitiveSize = math.max(geometry.Size, new float3());
m_PrimitiveOrientation = orientation;
m_ConvexHullGenerationParameters.BevelRadius = geometry.BevelRadius;
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
}
public void SetCapsule(CapsuleGeometryAuthoring geometry)
{
m_ShapeType = ShapeType.Capsule;
m_PrimitiveCenter = geometry.Center;
m_PrimitiveOrientation = geometry.OrientationEuler;
var radius = math.max(0f, geometry.Radius);
var height = math.max(0f, geometry.Height);
m_PrimitiveSize = new float3(radius * 2f, radius * 2f, height);
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
}
public void SetCylinder(CylinderGeometry geometry)
{
var euler = m_PrimitiveOrientation;
euler.SetValue(geometry.Orientation);
SetCylinder(geometry, euler);
}
internal void SetCylinder(CylinderGeometry geometry, EulerAngles orientation)
{
m_ShapeType = ShapeType.Cylinder;
m_PrimitiveCenter = geometry.Center;
m_PrimitiveOrientation = orientation;
geometry.Radius = math.max(0f, geometry.Radius);
geometry.Height = math.max(0f, geometry.Height);
m_PrimitiveSize = new float3(geometry.Radius * 2f, geometry.Radius * 2f, geometry.Height);
m_ConvexHullGenerationParameters.BevelRadius = geometry.BevelRadius;
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
}
public void SetSphere(SphereGeometry geometry, quaternion orientation)
{
var euler = m_PrimitiveOrientation;
euler.SetValue(orientation);
SetSphere(geometry, euler);
}
internal void SetSphere(SphereGeometry geometry)
{
SetSphere(geometry, m_PrimitiveOrientation);
}
internal void SetSphere(SphereGeometry geometry, EulerAngles orientation)
{
m_ShapeType = ShapeType.Sphere;
m_PrimitiveCenter = geometry.Center;
var radius = math.max(0f, geometry.Radius);
m_PrimitiveSize = new float3(2f * radius, 2f * radius, 2f * radius);
m_PrimitiveOrientation = orientation;
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
}
public void SetPlane(float3 center, float2 size, quaternion orientation)
{
var euler = m_PrimitiveOrientation;
euler.SetValue(orientation);
SetPlane(center, size, euler);
}
internal void SetPlane(float3 center, float2 size, EulerAngles orientation)
{
m_ShapeType = ShapeType.Plane;
m_PrimitiveCenter = center;
m_PrimitiveOrientation = orientation;
m_PrimitiveSize = new float3(size.x, 0f, size.y);
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
}
public void SetConvexHull(
ConvexHullGenerationParameters hullGenerationParameters, float minimumSkinnedVertexWeight
)
{
m_MinimumSkinnedVertexWeight = minimumSkinnedVertexWeight;
SetConvexHull(hullGenerationParameters);
}
public void SetConvexHull(ConvexHullGenerationParameters hullGenerationParameters, UnityEngine.Mesh customMesh = null)
{
m_ShapeType = ShapeType.ConvexHull;
m_CustomMesh = customMesh;
hullGenerationParameters.OnValidate();
m_ConvexHullGenerationParameters = hullGenerationParameters;
}
public void SetMesh(UnityEngine.Mesh mesh = null)
{
m_ShapeType = ShapeType.Mesh;
m_CustomMesh = mesh;
}
void OnEnable()
{
// included so tick box appears in Editor
}
const int k_LatestVersion = 1;
[SerializeField]
int m_SerializedVersion = 0;
void ISerializationCallbackReceiver.OnBeforeSerialize() {}
void ISerializationCallbackReceiver.OnAfterDeserialize() => UpgradeVersionIfNecessary();
#pragma warning disable 618
void UpgradeVersionIfNecessary()
{
if (m_SerializedVersion < k_LatestVersion)
{
// old data from version < 1 have been removed
if (m_SerializedVersion < 1)
m_SerializedVersion = 1;
}
}
#pragma warning restore 618
static void Validate(ref CylindricalProperties props)
{
props.Height = math.max(0f, props.Height);
props.Radius = math.max(0f, props.Radius);
}
void OnValidate()
{
UpgradeVersionIfNecessary();
m_PrimitiveSize = math.max(m_PrimitiveSize, new float3());
Validate(ref m_Capsule);
Validate(ref m_Cylinder);
switch (m_ShapeType)
{
case ShapeType.Box:
SetBox(GetBoxProperties(out var orientation), orientation);
break;
case ShapeType.Capsule:
SetCapsule(GetCapsuleProperties());
break;
case ShapeType.Cylinder:
SetCylinder(GetCylinderProperties(out orientation), orientation);
break;
case ShapeType.Sphere:
SetSphere(GetSphereProperties(out orientation), orientation);
break;
case ShapeType.Plane:
GetPlaneProperties(out var center, out var size2D, out orientation);
SetPlane(center, size2D, orientation);
break;
case ShapeType.ConvexHull:
case ShapeType.Mesh:
break;
default:
throw new UnimplementedShapeException(m_ShapeType);
}
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
m_CylinderSideCount =
math.clamp(m_CylinderSideCount, CylinderGeometry.MinSideCount, CylinderGeometry.MaxSideCount);
m_ConvexHullGenerationParameters.OnValidate();
PhysicsMaterialProperties.OnValidate(ref m_Material, true);
}
// matrix to transform point from shape space into world space
public float4x4 GetShapeToWorldMatrix() =>
new float4x4(Math.DecomposeRigidBodyTransform(transform.localToWorldMatrix));
// matrix to transform point from object's local transform matrix into shape space
internal float4x4 GetLocalToShapeMatrix() =>
math.mul(math.inverse(GetShapeToWorldMatrix()), transform.localToWorldMatrix);
internal unsafe void BakePoints(NativeArray<float3> points)
{
var localToShapeQuantized = GetLocalToShapeMatrix();
using (var aabb = new NativeArray<Aabb>(1, Allocator.TempJob))
{
new PhysicsShapeExtensions.GetAabbJob { Points = points, Aabb = aabb }.Run();
HashableShapeInputs.GetQuantizedTransformations(localToShapeQuantized, aabb[0], out localToShapeQuantized);
}
using (var bakedPoints = new NativeArray<float3>(points.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory))
{
new BakePointsJob
{
Points = points,
LocalToShape = localToShapeQuantized,
Output = bakedPoints
}.Schedule(points.Length, 16).Complete();
UnsafeUtility.MemCpy(points.GetUnsafePtr(), bakedPoints.GetUnsafePtr(), points.Length * UnsafeUtility.SizeOf<float3>());
}
}
[BurstCompile]
struct BakePointsJob : IJobParallelFor
{
[Collections.ReadOnly]
public NativeArray<float3> Points;
public float4x4 LocalToShape;
public NativeArray<float3> Output;
public void Execute(int index) => Output[index] = math.mul(LocalToShape, new float4(Points[index], 1f)).xyz;
}
/// <summary>
/// Fit this shape to render geometry in its GameObject hierarchy. Children in the hierarchy will
/// influence the result if they have enabled MeshRenderer components or have vertices bound to
/// them on a SkinnedMeshRenderer. Children will only count as influences if this shape is the
/// first ancestor shape in their hierarchy. As such, you should add shape components to all
/// GameObjects that should have them before you call this method on any of them.
/// </summary>
///
/// <exception cref="UnimplementedShapeException"> Thrown when an Unimplemented Shape error
/// condition occurs. </exception>
///
/// <param name="minimumSkinnedVertexWeight"> (Optional)
/// The minimum total weight that a vertex in a skinned mesh must have assigned to this object
/// and/or any of its influencing children. </param>
public void FitToEnabledRenderMeshes(float minimumSkinnedVertexWeight = 0f)
{
var shapeType = m_ShapeType;
m_MinimumSkinnedVertexWeight = minimumSkinnedVertexWeight;
using (var points = new NativeList<float3>(65535, Allocator.Persistent))
{
// temporarily un-assign custom mesh and assume this shape is a convex hull
var customMesh = m_CustomMesh;
m_CustomMesh = null;
GetConvexHullProperties(points, Application.isPlaying, default, default, default, default);
m_CustomMesh = customMesh;
if (points.Length == 0)
return;
// TODO: find best rotation, particularly if any points came from skinned mesh
var orientation = quaternion.identity;
var bounds = new Bounds(points[0], float3.zero);
for (int i = 1, count = points.Length; i < count; ++i)
bounds.Encapsulate(points[i]);
SetBox(
new BoxGeometry
{
Center = bounds.center,
Size = bounds.size,
Orientation = orientation,
BevelRadius = m_ConvexHullGenerationParameters.BevelRadius
}
);
}
switch (shapeType)
{
case ShapeType.Capsule:
SetCapsule(GetCapsuleProperties());
break;
case ShapeType.Cylinder:
SetCylinder(GetCylinderProperties(out var orientation), orientation);
break;
case ShapeType.Sphere:
SetSphere(GetSphereProperties(out orientation), orientation);
break;
case ShapeType.Plane:
// force recalculation of plane orientation by making it think shape type is out of date
m_ShapeType = ShapeType.Box;
GetPlaneProperties(out var center, out var size2D, out orientation);
SetPlane(center, size2D, orientation);
break;
case ShapeType.Box:
case ShapeType.ConvexHull:
case ShapeType.Mesh:
m_ShapeType = shapeType;
break;
default:
throw new UnimplementedShapeException(shapeType);
}
SyncCapsuleProperties();
SyncCylinderProperties();
SyncSphereProperties();
}
[Conditional("UNITY_EDITOR")]
void Reset()
{
#if UNITY_EDITOR
InitializeConvexHullGenerationParameters();
FitToEnabledRenderMeshes(m_MinimumSkinnedVertexWeight);
// TODO: also pick best primitive shape
UnityEditor.SceneView.RepaintAll();
#endif
}
public void InitializeConvexHullGenerationParameters()
{
var pointCloud = new NativeList<float3>(65535, Allocator.Temp);
GetConvexHullProperties(pointCloud, false, default, default, default, default);
m_ConvexHullGenerationParameters.InitializeToRecommendedAuthoringValues(pointCloud.AsArray());
}
}
}
fileFormatVersion: 2
guid: b275e5f92732148048d7b77e264ac30e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Serialization;
namespace Unity.Physics.Authoring
{
[CreateAssetMenu(menuName = "Unity Physics/Custom Physics Material Tag Names", fileName = "Custom Material Tag Names", order = 506)]
public sealed partial class CustomPhysicsMaterialTagNames : ScriptableObject, ITagNames
{
CustomPhysicsMaterialTagNames() {}
public IReadOnlyList<string> TagNames => m_TagNames;
[SerializeField]
[FormerlySerializedAs("m_FlagNames")]
string[] m_TagNames = Enumerable.Range(0, 8).Select(i => string.Empty).ToArray();
void OnValidate()
{
if (m_TagNames.Length != 8)
Array.Resize(ref m_TagNames, 8);
}
}
}
fileFormatVersion: 2
guid: 7c8956dd10f66427faa4a4067c5dd97d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7c7a0159cb0d5433b90c970978f6cf5c, type: 3}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
namespace Unity.Physics.Authoring
{
[Serializable]
public struct CustomPhysicsMaterialTags : IEquatable<CustomPhysicsMaterialTags>
{
public static CustomPhysicsMaterialTags Everything => new CustomPhysicsMaterialTags { Value = unchecked((byte)~0) };
public static CustomPhysicsMaterialTags Nothing => new CustomPhysicsMaterialTags { Value = 0 };
public bool Tag00;
public bool Tag01;
public bool Tag02;
public bool Tag03;
public bool Tag04;
public bool Tag05;
public bool Tag06;
public bool Tag07;
internal bool this[int i]
{
get
{
SafetyChecks.CheckInRangeAndThrow(i, new int2(0, 7), nameof(i));
switch (i)
{
case 0: return Tag00;
case 1: return Tag01;
case 2: return Tag02;
case 3: return Tag03;
case 4: return Tag04;
case 5: return Tag05;
case 6: return Tag06;
case 7: return Tag07;
default: return default;
}
}
set
{
SafetyChecks.CheckInRangeAndThrow(i, new int2(0, 7), nameof(i));
switch (i)
{
case 0: Tag00 = value; break;
case 1: Tag01 = value; break;
case 2: Tag02 = value; break;
case 3: Tag03 = value; break;
case 4: Tag04 = value; break;
case 5: Tag05 = value; break;
case 6: Tag06 = value; break;
case 7: Tag07 = value; break;
}
}
}
public byte Value
{
get
{
var result = 0;
result |= (Tag00 ? 1 : 0) << 0;
result |= (Tag01 ? 1 : 0) << 1;
result |= (Tag02 ? 1 : 0) << 2;
result |= (Tag03 ? 1 : 0) << 3;
result |= (Tag04 ? 1 : 0) << 4;
result |= (Tag05 ? 1 : 0) << 5;
result |= (Tag06 ? 1 : 0) << 6;
result |= (Tag07 ? 1 : 0) << 7;
return (byte)result;
}
set
{
Tag00 = (value & (1 << 0)) != 0;
Tag01 = (value & (1 << 1)) != 0;
Tag02 = (value & (1 << 2)) != 0;
Tag03 = (value & (1 << 3)) != 0;
Tag04 = (value & (1 << 4)) != 0;
Tag05 = (value & (1 << 5)) != 0;
Tag06 = (value & (1 << 6)) != 0;
Tag07 = (value & (1 << 7)) != 0;
}
}
public bool Equals(CustomPhysicsMaterialTags other) => Value == other.Value;
public override bool Equals(object obj) => obj is CustomPhysicsMaterialTags other && Equals(other);
public override int GetHashCode() => Value;
}
}
fileFormatVersion: 2
guid: 05cffa1394b6f481ca7e686dfc6404b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
#if UNITY_EDITOR
using System.Linq;
using UnityEditor;
using UnityEditor.Build;
namespace Unity.Physics.Authoring
{
[InitializeOnLoad]
class EditorInitialization
{
static readonly string k_CustomDefine = "UNITY_PHYSICS_CUSTOM";
static EditorInitialization()
{
var fromBuildTargetGroup = NamedBuildTarget.FromBuildTargetGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
var definesStr = PlayerSettings.GetScriptingDefineSymbols(fromBuildTargetGroup);
var defines = definesStr.Split(';').ToList();
var found = defines.Find(define => define.Equals(k_CustomDefine));
if (found == null)
{
defines.Add(k_CustomDefine);
PlayerSettings.SetScriptingDefineSymbols(fromBuildTargetGroup, string.Join(";", defines.ToArray()));
}
}
}
}
#endif
fileFormatVersion: 2
guid: 23f03a5c38aa4a6e81448a178cc0a09f
timeCreated: 1680128866
\ No newline at end of file
fileFormatVersion: 2
guid: 7f26f023234dd844797f8158565ecb4f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
[BakingType]
public struct JointEntityBaking : IComponentData
{
public Entity Entity;
}
public class BallAndSocketJoint : BaseJoint
{
// Editor only settings
[HideInInspector]
public bool EditPivots;
[Tooltip("If checked, PositionLocal will snap to match PositionInConnectedEntity")]
public bool AutoSetConnected = true;
public float3 PositionLocal;
public float3 PositionInConnectedEntity;
public virtual void UpdateAuto()
{
if (AutoSetConnected)
{
RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA);
PositionInConnectedEntity = math.transform(bFromA, PositionLocal);
}
}
}
public abstract class JointBaker<T> : Baker<T> where T : BaseJoint
{
protected PhysicsConstrainedBodyPair GetConstrainedBodyPair(BaseJoint authoring)
{
return new PhysicsConstrainedBodyPair(
GetEntity(TransformUsageFlags.Dynamic),
authoring.ConnectedBody == null ? Entity.Null : GetEntity(authoring.ConnectedBody, TransformUsageFlags.Dynamic),
authoring.EnableCollision
);
}
public Entity CreateJointEntity(uint worldIndex, PhysicsConstrainedBodyPair constrainedBodyPair, PhysicsJoint joint)
{
using (var joints = new NativeArray<PhysicsJoint>(1, Allocator.Temp) { [0] = joint })
using (var jointEntities = new NativeList<Entity>(1, Allocator.Temp))
{
CreateJointEntities(worldIndex, constrainedBodyPair, joints, jointEntities);
return jointEntities[0];
}
}
public uint GetWorldIndex(Component c)
{
uint worldIndex = 0;
if (c)
{
var physicsBody = GetComponent<PhysicsBodyAuthoring>(c);
if (physicsBody != null)
{
worldIndex = physicsBody.WorldIndex;
}
}
return worldIndex;
}
public uint GetWorldIndexFromBaseJoint(BaseJoint authoring)
{
var physicsBody = GetComponent<PhysicsBodyAuthoring>(authoring);
uint worldIndex = physicsBody.WorldIndex;
if (authoring.ConnectedBody == null)
{
return worldIndex;
}
var connectedBody = GetComponent<PhysicsBodyAuthoring>(authoring.ConnectedBody);
if (connectedBody != null)
{
Assertions.Assert.AreEqual(worldIndex, connectedBody.WorldIndex);
}
return worldIndex;
}
public void CreateJointEntities(uint worldIndex, PhysicsConstrainedBodyPair constrainedBodyPair, NativeArray<PhysicsJoint> joints, NativeList<Entity> newJointEntities)
{
if (!joints.IsCreated || joints.Length == 0)
return;
if (newJointEntities.IsCreated)
newJointEntities.Clear();
else
newJointEntities = new NativeList<Entity>(joints.Length, Allocator.Temp);
// create all new joints
var multipleJoints = joints.Length > 1;
var entity = GetEntity(TransformUsageFlags.Dynamic);
for (var i = 0; i < joints.Length; ++i)
{
var jointEntity = CreateAdditionalEntity(TransformUsageFlags.Dynamic);
AddSharedComponent(jointEntity, new PhysicsWorldIndex(worldIndex));
AddComponent(jointEntity, constrainedBodyPair);
AddComponent(jointEntity, joints[i]);
newJointEntities.Add(jointEntity);
if (GetComponent<ModifyJointLimitsAuthoring>() != null)
{
AddComponent(jointEntity, new JointEntityBaking()
{
Entity = entity
});
AddSharedComponentManaged(jointEntity, new ModifyJointLimits());
}
}
if (multipleJoints)
{
// set companion buffers for new joints
for (var i = 0; i < joints.Length; ++i)
{
var companions = AddBuffer<PhysicsJointCompanion>(newJointEntities[i]);
for (var j = 0; j < joints.Length; ++j)
{
if (i == j)
continue;
companions.Add(new PhysicsJointCompanion {JointEntity = newJointEntities[j]});
}
}
}
}
}
class BallAndSocketJointBaker : JointBaker<BallAndSocketJoint>
{
public override void Bake(BallAndSocketJoint authoring)
{
authoring.UpdateAuto();
var physicsJoint = PhysicsJoint.CreateBallAndSocket(authoring.PositionLocal, authoring.PositionInConnectedEntity);
physicsJoint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, physicsJoint);
}
}
}
fileFormatVersion: 2
guid: 28a669fa0e32f734c9d34661ccdfd58d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Mathematics;
namespace Unity.Physics.Authoring
{
public abstract class BaseJoint : BaseBodyPairConnector
{
public bool EnableCollision;
public float3 MaxImpulse = float.PositiveInfinity;
void OnEnable()
{
// included so tick box appears in Editor
}
}
}
fileFormatVersion: 2
guid: 02bf6429cb18f3147ae5f7d8e3fd5f07
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
public class FreeHingeJoint : BallAndSocketJoint
{
// Editor only settings
[HideInInspector]
public bool EditAxes;
public float3 HingeAxisLocal;
public float3 HingeAxisInConnectedEntity;
public override void UpdateAuto()
{
base.UpdateAuto();
if (AutoSetConnected)
{
RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA);
HingeAxisInConnectedEntity = math.mul(bFromA.rot, HingeAxisLocal);
}
}
}
class FreeHingeJointBaker : JointBaker<FreeHingeJoint>
{
public override void Bake(FreeHingeJoint authoring)
{
authoring.UpdateAuto();
Math.CalculatePerpendicularNormalized(authoring.HingeAxisLocal, out var perpendicularLocal, out _);
Math.CalculatePerpendicularNormalized(authoring.HingeAxisInConnectedEntity, out var perpendicularConnected, out _);
var physicsJoint = PhysicsJoint.CreateHinge(
new BodyFrame {Axis = authoring.HingeAxisLocal, Position = authoring.PositionLocal, PerpendicularAxis = perpendicularLocal},
new BodyFrame {Axis = authoring.HingeAxisInConnectedEntity, Position = authoring.PositionInConnectedEntity, PerpendicularAxis = perpendicularConnected }
);
physicsJoint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, physicsJoint);
}
}
}
fileFormatVersion: 2
guid: e5dc8c079bffa454ca607aac63ea7e7a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
// This Joint allows you to lock one or more of the 6 degrees of freedom of a constrained body.
// This is achieved by combining the appropriate lower level 'constraint atoms' to form the higher level Joint.
// In this case Linear and Angular constraint atoms are combined.
// One use-case for this Joint could be to restrict a 3d simulation to a 2d plane.
public class LimitDOFJoint : BaseJoint
{
public bool3 LockLinearAxes;
public bool3 LockAngularAxes;
public PhysicsJoint CreateLimitDOFJoint(RigidTransform offset)
{
var constraints = new FixedList512Bytes<Constraint>();
if (math.any(LockLinearAxes))
{
constraints.Add(new Constraint
{
ConstrainedAxes = LockLinearAxes,
Type = ConstraintType.Linear,
Min = 0,
Max = 0,
SpringFrequency = Constraint.DefaultSpringFrequency,
DampingRatio = Constraint.DefaultDampingRatio,
MaxImpulse = MaxImpulse,
});
}
if (math.any(LockAngularAxes))
{
constraints.Add(new Constraint
{
ConstrainedAxes = LockAngularAxes,
Type = ConstraintType.Angular,
Min = 0,
Max = 0,
SpringFrequency = Constraint.DefaultSpringFrequency,
DampingRatio = Constraint.DefaultDampingRatio,
MaxImpulse = MaxImpulse,
});
}
var joint = new PhysicsJoint
{
BodyAFromJoint = BodyFrame.Identity,
BodyBFromJoint = offset
};
joint.SetConstraints(constraints);
return joint;
}
}
class LimitDOFJointBaker : Baker<LimitDOFJoint>
{
public Entity CreateJointEntity(uint worldIndex, PhysicsConstrainedBodyPair constrainedBodyPair, PhysicsJoint joint)
{
using (var joints = new NativeArray<PhysicsJoint>(1, Allocator.Temp) { [0] = joint })
using (var jointEntities = new NativeList<Entity>(1, Allocator.Temp))
{
CreateJointEntities(worldIndex, constrainedBodyPair, joints, jointEntities);
return jointEntities[0];
}
}
public void CreateJointEntities(uint worldIndex, PhysicsConstrainedBodyPair constrainedBodyPair, NativeArray<PhysicsJoint> joints, NativeList<Entity> newJointEntities = default)
{
if (!joints.IsCreated || joints.Length == 0)
return;
if (newJointEntities.IsCreated)
newJointEntities.Clear();
else
newJointEntities = new NativeList<Entity>(joints.Length, Allocator.Temp);
// create all new joints
var multipleJoints = joints.Length > 1;
for (var i = 0; i < joints.Length; ++i)
{
var jointEntity = CreateAdditionalEntity(TransformUsageFlags.Dynamic);
AddSharedComponent(jointEntity, new PhysicsWorldIndex(worldIndex));
AddComponent(jointEntity, constrainedBodyPair);
AddComponent(jointEntity, joints[i]);
newJointEntities.Add(jointEntity);
}
if (multipleJoints)
{
// set companion buffers for new joints
for (var i = 0; i < joints.Length; ++i)
{
var companions = AddBuffer<PhysicsJointCompanion>(newJointEntities[i]);
for (var j = 0; j < joints.Length; ++j)
{
if (i == j)
continue;
companions.Add(new PhysicsJointCompanion {JointEntity = newJointEntities[j]});
}
}
}
}
protected PhysicsConstrainedBodyPair GetConstrainedBodyPair(LimitDOFJoint authoring)
{
return new PhysicsConstrainedBodyPair(
GetEntity(TransformUsageFlags.Dynamic),
authoring.ConnectedBody == null ? Entity.Null : GetEntity(authoring.ConnectedBody, TransformUsageFlags.Dynamic),
authoring.EnableCollision
);
}
public uint GetWorldIndex(Component c)
{
uint worldIndex = 0;
var physicsBody = GetComponent<PhysicsBodyAuthoring>(c);
if (physicsBody != null)
{
worldIndex = physicsBody.WorldIndex;
}
return worldIndex;
}
public override void Bake(LimitDOFJoint authoring)
{
if (!math.any(authoring.LockLinearAxes) && !math.any(authoring.LockAngularAxes))
return;
RigidTransform bFromA = math.mul(math.inverse(authoring.worldFromB), authoring.worldFromA);
PhysicsJoint physicsJoint = authoring.CreateLimitDOFJoint(bFromA);
var worldIndex = GetWorldIndex(authoring);
CreateJointEntity(
worldIndex,
GetConstrainedBodyPair(authoring),
physicsJoint
);
}
}
}
fileFormatVersion: 2
guid: 9457d04025dadec4b85ae39dad2e1822
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using static Unity.Physics.Math;
namespace Unity.Physics.Authoring
{
public class LimitedDistanceJoint : BallAndSocketJoint
{
public float MinDistance;
public float MaxDistance;
}
class LimitedDistanceJointBaker : JointBaker<LimitedDistanceJoint>
{
public override void Bake(LimitedDistanceJoint authoring)
{
authoring.UpdateAuto();
var physicsJoint = PhysicsJoint.CreateLimitedDistance(authoring.PositionLocal, authoring.PositionInConnectedEntity, new FloatRange(authoring.MinDistance, authoring.MaxDistance));
physicsJoint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, physicsJoint);
}
}
}
fileFormatVersion: 2
guid: d79d98418b67aa44db932451943018a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using static Unity.Physics.Math;
namespace Unity.Physics.Authoring
{
public class LimitedHingeJoint : FreeHingeJoint
{
// Editor only settings
[HideInInspector]
public bool EditLimits;
public float3 PerpendicularAxisLocal;
public float3 PerpendicularAxisInConnectedEntity;
public float MinAngle;
public float MaxAngle;
public override void UpdateAuto()
{
base.UpdateAuto();
if (AutoSetConnected)
{
RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA);
HingeAxisInConnectedEntity = math.mul(bFromA.rot, HingeAxisLocal);
PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, PerpendicularAxisLocal);
}
}
}
class LimitedHingeJointBaker : JointBaker<LimitedHingeJoint>
{
public override void Bake(LimitedHingeJoint authoring)
{
authoring.UpdateAuto();
var physicsJoint = PhysicsJoint.CreateLimitedHinge(
new BodyFrame
{
Axis = math.normalize(authoring.HingeAxisLocal),
PerpendicularAxis = math.normalize(authoring.PerpendicularAxisLocal),
Position = authoring.PositionLocal
},
new BodyFrame
{
Axis = math.normalize(authoring.HingeAxisInConnectedEntity),
PerpendicularAxis = math.normalize(authoring.PerpendicularAxisInConnectedEntity),
Position = authoring.PositionInConnectedEntity
},
math.radians(new FloatRange(authoring.MinAngle, authoring.MaxAngle))
);
physicsJoint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, physicsJoint);
}
}
}
fileFormatVersion: 2
guid: cbaf9813ee7af2f41a5fd776598ab5b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Physics;
using Unity.Physics.Authoring;
using Unity.Physics.Extensions;
using Unity.Physics.Systems;
using UnityEngine;
using FloatRange = Unity.Physics.Math.FloatRange;
namespace Unity.Physics.Authoring
{
// stores an initial value and a pair of scalar curves to apply to relevant constraints on the joint
struct ModifyJointLimits : ISharedComponentData, IEquatable<ModifyJointLimits>
{
public PhysicsJoint InitialValue;
public ParticleSystem.MinMaxCurve AngularRangeScalar;
public ParticleSystem.MinMaxCurve LinearRangeScalar;
public bool Equals(ModifyJointLimits other) =>
AngularRangeScalar.Equals(other.AngularRangeScalar) && LinearRangeScalar.Equals(other.LinearRangeScalar);
public override bool Equals(object obj) => obj is ModifyJointLimits other && Equals(other);
public override int GetHashCode() =>
unchecked((AngularRangeScalar.GetHashCode() * 397) ^ LinearRangeScalar.GetHashCode());
}
// an authoring component to add to a GameObject with one or more Joint
public class ModifyJointLimitsAuthoring : MonoBehaviour
{
public ParticleSystem.MinMaxCurve AngularRangeScalar = new ParticleSystem.MinMaxCurve(
1f,
min: new AnimationCurve(
new Keyframe(0f, 0f, 0f, 0f),
new Keyframe(2f, -2f, 0f, 0f),
new Keyframe(4f, 0f, 0f, 0f)
)
{
preWrapMode = WrapMode.Loop,
postWrapMode = WrapMode.Loop
},
max: new AnimationCurve(
new Keyframe(0f, 1f, 0f, 0f),
new Keyframe(2f, -1f, 0f, 0f),
new Keyframe(4f, 1f, 0f, 0f)
)
{
preWrapMode = WrapMode.Loop,
postWrapMode = WrapMode.Loop
}
);
public ParticleSystem.MinMaxCurve LinearRangeScalar = new ParticleSystem.MinMaxCurve(
1f,
min: new AnimationCurve(
new Keyframe(0f, 1f, 0f, 0f),
new Keyframe(2f, 0.5f, 0f, 0f),
new Keyframe(4f, 1f, 0f, 0f)
)
{
preWrapMode = WrapMode.Loop,
postWrapMode = WrapMode.Loop
},
max: new AnimationCurve(
new Keyframe(0f, 0.5f, 0f, 0f),
new Keyframe(2f, 0f, 0f, 0f),
new Keyframe(4f, 0.5f, 0f, 0f)
)
{
preWrapMode = WrapMode.Loop,
postWrapMode = WrapMode.Loop
}
);
}
[BakingType]
public class ModifyJointLimitsBakingData : IComponentData
{
public ParticleSystem.MinMaxCurve AngularRangeScalar;
public ParticleSystem.MinMaxCurve LinearRangeScalar;
}
class ModifyJointLimitsBaker : Baker<ModifyJointLimitsAuthoring>
{
public override void Bake(ModifyJointLimitsAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponentObject(entity, new ModifyJointLimitsBakingData
{
AngularRangeScalar = authoring.AngularRangeScalar,
LinearRangeScalar = authoring.LinearRangeScalar
});
}
}
// after joints have been converted, find the entities they produced and add ModifyJointLimits to them
[UpdateAfter(typeof(EndJointBakingSystem))]
[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]
partial struct ModifyJointLimitsBakingSystem : ISystem
{
private EntityQuery _ModifyJointLimitsBakingDataQuery;
private EntityQuery _JointEntityBakingQuery;
public void OnCreate(ref SystemState state)
{
_ModifyJointLimitsBakingDataQuery = state.GetEntityQuery(new EntityQueryDesc
{
All = new[] {ComponentType.ReadOnly<ModifyJointLimitsBakingData>()},
Options = EntityQueryOptions.IncludeDisabledEntities | EntityQueryOptions.IncludePrefab
});
_JointEntityBakingQuery = state.GetEntityQuery(new EntityQueryDesc
{
All = new[] {ComponentType.ReadOnly<JointEntityBaking>()}
});
_ModifyJointLimitsBakingDataQuery.AddChangedVersionFilter(typeof(ModifyJointLimitsBakingData));
_JointEntityBakingQuery.AddChangedVersionFilter(typeof(JointEntityBaking));
}
public void OnUpdate(ref SystemState state)
{
if (_ModifyJointLimitsBakingDataQuery.IsEmpty && _JointEntityBakingQuery.IsEmpty)
{
return;
}
// Collect all the joints
NativeParallelMultiHashMap<Entity, (Entity, PhysicsJoint)> jointsLookUp =
new NativeParallelMultiHashMap<Entity, (Entity, PhysicsJoint)>(10, Allocator.TempJob);
foreach (var(jointEntity, physicsJoint, entity) in SystemAPI
.Query<RefRO<JointEntityBaking>, RefRO<PhysicsJoint>>().WithEntityAccess()
.WithOptions(EntityQueryOptions.IncludeDisabledEntities | EntityQueryOptions.IncludePrefab))
{
jointsLookUp.Add(jointEntity.ValueRO.Entity, (entity, physicsJoint.ValueRO));
}
foreach (var(modifyJointLimits, entity) in SystemAPI.Query<ModifyJointLimitsBakingData>()
.WithEntityAccess().WithOptions(EntityQueryOptions.IncludeDisabledEntities |
EntityQueryOptions.IncludePrefab))
{
var angularModification = new ParticleSystem.MinMaxCurve(
multiplier: math.radians(modifyJointLimits.AngularRangeScalar.curveMultiplier),
min: modifyJointLimits.AngularRangeScalar.curveMin,
max: modifyJointLimits.AngularRangeScalar.curveMax
);
foreach (var joint in jointsLookUp.GetValuesForKey(entity))
{
state.EntityManager.SetSharedComponentManaged(joint.Item1, new ModifyJointLimits
{
InitialValue = joint.Item2,
AngularRangeScalar = angularModification,
LinearRangeScalar = modifyJointLimits.LinearRangeScalar
});
}
}
jointsLookUp.Dispose();
}
}
// apply an animated effect to the limits on supported types of joints
[RequireMatchingQueriesForUpdate]
[UpdateInGroup(typeof(PhysicsSystemGroup), OrderLast = true)]
partial struct ModifyJointLimitsSystem : ISystem
{
public void OnUpdate(ref SystemState state)
{
var time = (float)SystemAPI.Time.ElapsedTime;
foreach (var(joint, modification) in SystemAPI.Query<RefRW<PhysicsJoint>, ModifyJointLimits>())
{
var animatedAngularScalar = new FloatRange(
modification.AngularRangeScalar.curveMin.Evaluate(time),
modification.AngularRangeScalar.curveMax.Evaluate(time)
);
var animatedLinearScalar = new FloatRange(
modification.LinearRangeScalar.curveMin.Evaluate(time),
modification.LinearRangeScalar.curveMax.Evaluate(time)
);
// in each case, get relevant properties from the initial value based on joint type, and apply scalar
switch (joint.ValueRW.JointType)
{
// Custom type could be anything, so this demo just applies changes to all constraints
case JointType.Custom:
var constraints = modification.InitialValue.GetConstraints();
for (var i = 0; i < constraints.Length; i++)
{
var constraint = constraints[i];
var isAngular = constraint.Type == ConstraintType.Angular;
var scalar = math.select(animatedLinearScalar, animatedAngularScalar, isAngular);
var constraintRange = (FloatRange)(new float2(constraint.Min, constraint.Max) * scalar);
constraint.Min = constraintRange.Min;
constraint.Max = constraintRange.Max;
constraints[i] = constraint;
}
joint.ValueRW.SetConstraints(constraints);
break;
// other types have corresponding getters/setters to retrieve more meaningful data
case JointType.LimitedDistance:
var distanceRange = modification.InitialValue.GetLimitedDistanceRange();
joint.ValueRW.SetLimitedDistanceRange(distanceRange * (float2)animatedLinearScalar);
break;
case JointType.LimitedHinge:
var angularRange = modification.InitialValue.GetLimitedHingeRange();
joint.ValueRW.SetLimitedHingeRange(angularRange * (float2)animatedAngularScalar);
break;
case JointType.Prismatic:
var distanceOnAxis = modification.InitialValue.GetPrismaticRange();
joint.ValueRW.SetPrismaticRange(distanceOnAxis * (float2)animatedLinearScalar);
break;
// ragdoll joints are composed of two separate joints with different meanings
case JointType.RagdollPrimaryCone:
modification.InitialValue.GetRagdollPrimaryConeAndTwistRange(
out var maxConeAngle,
out var angularTwistRange
);
joint.ValueRW.SetRagdollPrimaryConeAndTwistRange(
maxConeAngle * animatedAngularScalar.Max,
angularTwistRange * (float2)animatedAngularScalar
);
break;
case JointType.RagdollPerpendicularCone:
var angularPlaneRange = modification.InitialValue.GetRagdollPerpendicularConeRange();
joint.ValueRW.SetRagdollPerpendicularConeRange(angularPlaneRange *
(float2)animatedAngularScalar);
break;
// remaining types have no limits on their Constraint atoms to meaningfully modify
case JointType.BallAndSocket:
case JointType.Fixed:
case JointType.Hinge:
break;
}
}
}
}
}
fileFormatVersion: 2
guid: 09435b2483c7b48409764517bbfff081
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
using static Unity.Physics.Math;
namespace Unity.Physics.Authoring
{
public class PrismaticJoint : BallAndSocketJoint
{
public float3 AxisLocal;
public float3 AxisInConnectedEntity;
public float3 PerpendicularAxisLocal;
public float3 PerpendicularAxisInConnectedEntity;
public float MinDistanceOnAxis;
public float MaxDistanceOnAxis;
public override void UpdateAuto()
{
base.UpdateAuto();
if (AutoSetConnected)
{
RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA);
AxisInConnectedEntity = math.mul(bFromA.rot, AxisLocal);
PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, PerpendicularAxisLocal);
}
}
}
class PrismaticJointBaker : JointBaker<PrismaticJoint>
{
public override void Bake(PrismaticJoint authoring)
{
authoring.UpdateAuto();
var physicsJoint = PhysicsJoint.CreatePrismatic(
new BodyFrame
{
Axis = authoring.AxisLocal,
PerpendicularAxis = authoring.PerpendicularAxisLocal,
Position = authoring.PositionLocal
},
new BodyFrame
{
Axis = authoring.AxisInConnectedEntity,
PerpendicularAxis = authoring.PerpendicularAxisInConnectedEntity,
Position = authoring.PositionInConnectedEntity
},
new FloatRange(authoring.MinDistanceOnAxis, authoring.MaxDistanceOnAxis)
);
physicsJoint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, physicsJoint);
}
}
}
fileFormatVersion: 2
guid: b226e7ae02ee34c458747d6c2ee8456c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using static Unity.Physics.Math;
namespace Unity.Physics.Authoring
{
public class RagdollJoint : BallAndSocketJoint
{
const int k_LatestVersion = 1;
// Editor only settings
[HideInInspector]
public bool EditAxes;
[HideInInspector]
public bool EditLimits;
[SerializeField]
int m_Version;
public float3 TwistAxisLocal;
public float3 TwistAxisInConnectedEntity;
public float3 PerpendicularAxisLocal;
public float3 PerpendicularAxisInConnectedEntity;
public float MaxConeAngle;
public float MinPerpendicularAngle;
public float MaxPerpendicularAngle;
public float MinTwistAngle;
public float MaxTwistAngle;
internal void UpgradeVersionIfNecessary()
{
if (m_Version >= k_LatestVersion)
return;
MinPerpendicularAngle -= 90f;
MaxPerpendicularAngle -= 90f;
m_Version = k_LatestVersion;
}
void OnValidate()
{
UpgradeVersionIfNecessary();
MaxConeAngle = math.clamp(MaxConeAngle, 0f, 180f);
MaxPerpendicularAngle = math.clamp(MaxPerpendicularAngle, -90f, 90f);
MinPerpendicularAngle = math.clamp(MinPerpendicularAngle, -90f, 90f);
if (MaxPerpendicularAngle < MinPerpendicularAngle)
{
var swap = new FloatRange(MinPerpendicularAngle, MaxPerpendicularAngle).Sorted();
MinPerpendicularAngle = swap.Min;
MaxPerpendicularAngle = swap.Max;
}
MinTwistAngle = math.clamp(MinTwistAngle, -180f, 180f);
MaxTwistAngle = math.clamp(MaxTwistAngle, -180f, 180f);
if (MaxTwistAngle < MinTwistAngle)
{
var swap = new FloatRange(MinTwistAngle, MaxTwistAngle).Sorted();
MinTwistAngle = swap.Min;
MaxTwistAngle = swap.Max;
}
}
public override void UpdateAuto()
{
base.UpdateAuto();
if (AutoSetConnected)
{
RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA);
TwistAxisInConnectedEntity = math.mul(bFromA.rot, TwistAxisLocal);
PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, PerpendicularAxisLocal);
}
}
}
class RagdollJointBaker : JointBaker<RagdollJoint>
{
public override void Bake(RagdollJoint authoring)
{
authoring.UpdateAuto();
authoring.UpgradeVersionIfNecessary();
PhysicsJoint.CreateRagdoll(
new BodyFrame { Axis = authoring.TwistAxisLocal, PerpendicularAxis = authoring.PerpendicularAxisLocal, Position = authoring.PositionLocal },
new BodyFrame { Axis = authoring.TwistAxisInConnectedEntity, PerpendicularAxis = authoring.PerpendicularAxisInConnectedEntity, Position = authoring.PositionInConnectedEntity },
math.radians(authoring.MaxConeAngle),
math.radians(new FloatRange(authoring.MinPerpendicularAngle, authoring.MaxPerpendicularAngle)),
math.radians(new FloatRange(authoring.MinTwistAngle, authoring.MaxTwistAngle)),
out var primaryCone,
out var perpendicularCone
);
primaryCone.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
perpendicularCone.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
using NativeList<Entity> entities = new NativeList<Entity>(1, Allocator.TempJob);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntities(worldIndex,
constraintBodyPair,
new NativeArray<PhysicsJoint>(2, Allocator.Temp) { [0] = primaryCone, [1] = perpendicularCone }, entities);
}
}
}
fileFormatVersion: 2
guid: de6dfad1dfcc06c42be6f68e1413c3c4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
namespace Unity.Physics.Authoring
{
public class RigidJoint : BallAndSocketJoint
{
public quaternion OrientationLocal = quaternion.identity;
public quaternion OrientationInConnectedEntity = quaternion.identity;
public override void UpdateAuto()
{
base.UpdateAuto();
if (AutoSetConnected)
{
RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA);
OrientationInConnectedEntity = math.mul(bFromA.rot, OrientationLocal);
}
{
OrientationLocal = math.normalize(OrientationLocal);
OrientationInConnectedEntity = math.normalize(OrientationInConnectedEntity);
}
}
}
class RigidJointBaker : JointBaker<RigidJoint>
{
public override void Bake(RigidJoint authoring)
{
authoring.UpdateAuto();
var physicsJoint = PhysicsJoint.CreateFixed(
new RigidTransform(authoring.OrientationLocal, authoring.PositionLocal),
new RigidTransform(authoring.OrientationInConnectedEntity, authoring.PositionInConnectedEntity)
);
physicsJoint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, physicsJoint);
}
}
}
fileFormatVersion: 2
guid: 994345d4b32d91b45a04e9ec5a6c2b46
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 0e3f6133a3c24774a35e94fc4d799eb3
timeCreated: 1647466700
\ No newline at end of file
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
public class AngularVelocityMotor : BaseJoint
{
[Tooltip("An offset from center of entity with motor. Representing the anchor/pivot point of rotation")]
public float3 PivotPosition;
[Tooltip("The axis of rotation of the motor. Value will be normalized")]
public float3 AxisOfRotation;
[Tooltip("Target speed for the motor to maintain, in degrees/s")]
public float TargetSpeed;
[Tooltip("The magnitude of the maximum impulse the motor can exert in a single step. Applies only to the motor constraint.")]
public float MaxImpulseAppliedByMotor = math.INFINITY;
private float3 PerpendicularAxisLocal;
private float3 PositionInConnectedEntity;
private float3 HingeAxisInConnectedEntity;
private float3 PerpendicularAxisInConnectedEntity;
class AngularVelocityMotorBaker : JointBaker<AngularVelocityMotor>
{
public override void Bake(AngularVelocityMotor authoring)
{
float3 axisInA = math.normalize(authoring.AxisOfRotation);
RigidTransform bFromA = math.mul(math.inverse(authoring.worldFromB), authoring.worldFromA);
authoring.PositionInConnectedEntity = math.transform(bFromA, authoring.PivotPosition); //position of motored body pivot relative to Connected Entity in world space
authoring.HingeAxisInConnectedEntity = math.mul(bFromA.rot, axisInA); //motor axis in Connected Entity space
// Always calculate the perpendicular axes
Math.CalculatePerpendicularNormalized(axisInA, out var perpendicularLocal, out _);
authoring.PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, perpendicularLocal); //perp motor axis in Connected Entity space
var joint = PhysicsJoint.CreateAngularVelocityMotor(
new BodyFrame
{
Axis = axisInA,
PerpendicularAxis = perpendicularLocal,
Position = authoring.PivotPosition
},
new BodyFrame
{
Axis = authoring.HingeAxisInConnectedEntity,
PerpendicularAxis = authoring.PerpendicularAxisInConnectedEntity,
Position = authoring.PositionInConnectedEntity
},
math.radians(authoring.TargetSpeed),
authoring.MaxImpulseAppliedByMotor
);
joint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, joint);
}
}
}
}
fileFormatVersion: 2
guid: 778b7bc40bf3f455a8432365763322fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
public class LinearVelocityMotor : BaseJoint
{
[Tooltip("An offset from the center of the body with the motor (bodyA), representing the anchor point of translation.")]
public float3 AnchorPosition;
[Tooltip("The direction of the motor, relative to the orientation of the Connected Body (bodyB). Value will be normalized")]
public float3 DirectionOfMovement;
[Tooltip("Motor will drive at this speed from the initial position of bodyA, along the Direction of Movement, in m/s.")]
public float TargetSpeed;
[Tooltip("The magnitude of the maximum impulse the motor can exert in a single step. Applies only to the motor constraint.")]
public float MaxImpulseAppliedByMotor = math.INFINITY;
private float3 PerpendicularAxisLocal;
private float3 PositionInConnectedEntity;
private float3 AxisInConnectedEntity;
private float3 PerpendicularAxisInConnectedEntity;
class LinearVelocityMotorBaker : JointBaker<LinearVelocityMotor>
{
public override void Bake(LinearVelocityMotor authoring)
{
float3 axisInB = math.normalize(authoring.DirectionOfMovement);
RigidTransform aFromB = math.mul(math.inverse(authoring.worldFromA), authoring.worldFromB);
float3 axisInA = math.mul(aFromB.rot, axisInB); //motor axis relative to bodyA
RigidTransform bFromA = math.mul(math.inverse(authoring.worldFromB), authoring.worldFromA);
authoring.PositionInConnectedEntity = math.transform(bFromA, authoring.AnchorPosition); //position of motored body relative to Connected Entity in world space
authoring.AxisInConnectedEntity = axisInB; //motor axis in Connected Entity space
// Always calculate the perpendicular axes
Math.CalculatePerpendicularNormalized(axisInA, out var perpendicularAxisLocal, out _);
authoring.PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, perpendicularAxisLocal); //perp motor axis in Connected Entity space
var joint = PhysicsJoint.CreateLinearVelocityMotor(
new BodyFrame
{
Axis = axisInA,
PerpendicularAxis = perpendicularAxisLocal,
Position = authoring.AnchorPosition
},
new BodyFrame
{
Axis = authoring.AxisInConnectedEntity,
PerpendicularAxis = authoring.PerpendicularAxisInConnectedEntity,
Position = authoring.PositionInConnectedEntity
},
authoring.TargetSpeed,
authoring.MaxImpulseAppliedByMotor
);
joint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, joint);
}
}
}
}
fileFormatVersion: 2
guid: 8ecb5a9d99c1e4324be6771b9b83142f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
public class PositionMotor : BaseJoint
{
[Tooltip("An offset from the center of the body with the motor, representing the anchor point of translation.")]
public float3 AnchorPosition;
[Tooltip("The direction of the motor, relative to the orientation of the Connected Body (bodyB). Value will be normalized")]
public float3 DirectionOfMovement;
[Tooltip("Motor will drive this length away from the anchor position of bodyA.")]
public float TargetDistance;
[Tooltip("The magnitude of the maximum impulse the motor can exert in a single step. Applies only to the motor constraint.")]
public float MaxImpulseAppliedByMotor = math.INFINITY;
private float3 PerpendicularAxisLocal;
private float3 PositionInConnectedEntity;
private float3 AxisInConnectedEntity;
private float3 PerpendicularAxisInConnectedEntity;
class PositionMotorBaker : JointBaker<PositionMotor>
{
public override void Bake(PositionMotor authoring)
{
float3 axisInB = math.normalize(authoring.DirectionOfMovement);
RigidTransform aFromB = math.mul(math.inverse(authoring.worldFromA), authoring.worldFromB);
float3 axisInA = math.mul(aFromB.rot, axisInB); //motor axis relative to bodyA
RigidTransform bFromA = math.mul(math.inverse(authoring.worldFromB), authoring.worldFromA);
authoring.PositionInConnectedEntity = math.transform(bFromA, authoring.AnchorPosition); //position of motored body relative to Connected Entity in world space
authoring.AxisInConnectedEntity = axisInB; //motor axis in Connected Entity space
// Always calculate the perpendicular axes
Math.CalculatePerpendicularNormalized(axisInA, out var perpendicularLocal, out _);
authoring.PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, perpendicularLocal); //perp motor axis in Connected Entity space
var joint = PhysicsJoint.CreatePositionMotor(
new BodyFrame
{
Axis = axisInA,
PerpendicularAxis = perpendicularLocal,
Position = authoring.AnchorPosition
},
new BodyFrame
{
Axis = authoring.AxisInConnectedEntity,
PerpendicularAxis = authoring.PerpendicularAxisInConnectedEntity,
Position = authoring.PositionInConnectedEntity
},
authoring.TargetDistance,
authoring.MaxImpulseAppliedByMotor
);
joint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, joint);
}
}
}
}
fileFormatVersion: 2
guid: 43a90fd2b152c41f2b0659c2f2feccfb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
public class RotationalMotor : BaseJoint
{
[Tooltip("An offset from center of entity with motor. Representing the anchor/pivot point of rotation")]
public float3 PivotPosition;
[Tooltip("The axis of rotation of the motor. Value will be normalized")]
public float3 AxisOfRotation;
[Tooltip("Motor will maintain this target angle around the AxisOfRotation, in degrees")]
public float TargetAngle;
[Tooltip("The magnitude of the maximum impulse the motor can exert in one step. Applies only to the motor constraint.")]
public float MaxImpulseAppliedByMotor = math.INFINITY;
private float3 PerpendicularAxisLocal;
private float3 PositionInConnectedEntity;
private float3 HingeAxisInConnectedEntity;
private float3 PerpendicularAxisInConnectedEntity;
class RotationalMotorBaker : JointBaker<RotationalMotor>
{
public override void Bake(RotationalMotor authoring)
{
float3 axisInA = math.normalize(authoring.AxisOfRotation);
RigidTransform bFromA = math.mul(math.inverse(authoring.worldFromB), authoring.worldFromA);
authoring.PositionInConnectedEntity = math.transform(bFromA, authoring.PivotPosition); //position of motored body pivot relative to Connected Entity in world space
authoring.HingeAxisInConnectedEntity = math.mul(bFromA.rot, axisInA); //motor axis in Connected Entity space
// Always calculate the perpendicular axes
Math.CalculatePerpendicularNormalized(axisInA, out var perpendicularLocal, out _);
authoring.PerpendicularAxisInConnectedEntity = math.mul(bFromA.rot, perpendicularLocal); //perp motor axis in Connected Entity space
var joint = PhysicsJoint.CreateRotationalMotor(
new BodyFrame
{
Axis = axisInA,
PerpendicularAxis = perpendicularLocal,
Position = authoring.PivotPosition
},
new BodyFrame
{
Axis = authoring.HingeAxisInConnectedEntity,
PerpendicularAxis = authoring.PerpendicularAxisInConnectedEntity,
Position = authoring.PositionInConnectedEntity
},
math.radians(authoring.TargetAngle),
authoring.MaxImpulseAppliedByMotor
);
joint.SetImpulseEventThresholdAllConstraints(authoring.MaxImpulse);
var constraintBodyPair = GetConstrainedBodyPair(authoring);
uint worldIndex = GetWorldIndexFromBaseJoint(authoring);
CreateJointEntity(worldIndex, constraintBodyPair, joint);
}
}
}
}
fileFormatVersion: 2
guid: ed690d210e6de4de5898e09e2bf1f336
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.Physics.Authoring
{
[CreateAssetMenu(menuName = "Unity Physics/Physics Category Names", fileName = "Physics Category Names", order = 507)]
public sealed class PhysicsCategoryNames : ScriptableObject, ITagNames
{
PhysicsCategoryNames() {}
IReadOnlyList<string> ITagNames.TagNames => CategoryNames;
public IReadOnlyList<string> CategoryNames => m_CategoryNames;
[SerializeField]
string[] m_CategoryNames = Enumerable.Range(0, 32).Select(i => string.Empty).ToArray();
void OnValidate()
{
if (m_CategoryNames.Length != 32)
Array.Resize(ref m_CategoryNames, 32);
}
}
}
fileFormatVersion: 2
guid: cea4b49c4d6784a3291bea84d8086c8e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 269c31d3570d84742a0d8739b06d5a18, type: 3}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
namespace Unity.Physics.Authoring
{
[Serializable]
public struct PhysicsCategoryTags : IEquatable<PhysicsCategoryTags>
{
public static PhysicsCategoryTags Everything => new PhysicsCategoryTags { Value = unchecked((uint)~0) };
public static PhysicsCategoryTags Nothing => new PhysicsCategoryTags { Value = 0 };
public bool Category00;
public bool Category01;
public bool Category02;
public bool Category03;
public bool Category04;
public bool Category05;
public bool Category06;
public bool Category07;
public bool Category08;
public bool Category09;
public bool Category10;
public bool Category11;
public bool Category12;
public bool Category13;
public bool Category14;
public bool Category15;
public bool Category16;
public bool Category17;
public bool Category18;
public bool Category19;
public bool Category20;
public bool Category21;
public bool Category22;
public bool Category23;
public bool Category24;
public bool Category25;
public bool Category26;
public bool Category27;
public bool Category28;
public bool Category29;
public bool Category30;
public bool Category31;
internal bool this[int i]
{
get
{
SafetyChecks.CheckInRangeAndThrow(i, new int2(0, 31), nameof(i));
switch (i)
{
case 0: return Category00;
case 1: return Category01;
case 2: return Category02;
case 3: return Category03;
case 4: return Category04;
case 5: return Category05;
case 6: return Category06;
case 7: return Category07;
case 8: return Category08;
case 9: return Category09;
case 10: return Category10;
case 11: return Category11;
case 12: return Category12;
case 13: return Category13;
case 14: return Category14;
case 15: return Category15;
case 16: return Category16;
case 17: return Category17;
case 18: return Category18;
case 19: return Category19;
case 20: return Category20;
case 21: return Category21;
case 22: return Category22;
case 23: return Category23;
case 24: return Category24;
case 25: return Category25;
case 26: return Category26;
case 27: return Category27;
case 28: return Category28;
case 29: return Category29;
case 30: return Category30;
case 31: return Category31;
default: return default;
}
}
set
{
SafetyChecks.CheckInRangeAndThrow(i, new int2(0, 31), nameof(i));
switch (i)
{
case 0: Category00 = value; break;
case 1: Category01 = value; break;
case 2: Category02 = value; break;
case 3: Category03 = value; break;
case 4: Category04 = value; break;
case 5: Category05 = value; break;
case 6: Category06 = value; break;
case 7: Category07 = value; break;
case 8: Category08 = value; break;
case 9: Category09 = value; break;
case 10: Category10 = value; break;
case 11: Category11 = value; break;
case 12: Category12 = value; break;
case 13: Category13 = value; break;
case 14: Category14 = value; break;
case 15: Category15 = value; break;
case 16: Category16 = value; break;
case 17: Category17 = value; break;
case 18: Category18 = value; break;
case 19: Category19 = value; break;
case 20: Category20 = value; break;
case 21: Category21 = value; break;
case 22: Category22 = value; break;
case 23: Category23 = value; break;
case 24: Category24 = value; break;
case 25: Category25 = value; break;
case 26: Category26 = value; break;
case 27: Category27 = value; break;
case 28: Category28 = value; break;
case 29: Category29 = value; break;
case 30: Category30 = value; break;
case 31: Category31 = value; break;
}
}
}
public uint Value
{
get
{
var result = 0;
result |= (Category00 ? 1 : 0) << 0;
result |= (Category01 ? 1 : 0) << 1;
result |= (Category02 ? 1 : 0) << 2;
result |= (Category03 ? 1 : 0) << 3;
result |= (Category04 ? 1 : 0) << 4;
result |= (Category05 ? 1 : 0) << 5;
result |= (Category06 ? 1 : 0) << 6;
result |= (Category07 ? 1 : 0) << 7;
result |= (Category08 ? 1 : 0) << 8;
result |= (Category09 ? 1 : 0) << 9;
result |= (Category10 ? 1 : 0) << 10;
result |= (Category11 ? 1 : 0) << 11;
result |= (Category12 ? 1 : 0) << 12;
result |= (Category13 ? 1 : 0) << 13;
result |= (Category14 ? 1 : 0) << 14;
result |= (Category15 ? 1 : 0) << 15;
result |= (Category16 ? 1 : 0) << 16;
result |= (Category17 ? 1 : 0) << 17;
result |= (Category18 ? 1 : 0) << 18;
result |= (Category19 ? 1 : 0) << 19;
result |= (Category20 ? 1 : 0) << 20;
result |= (Category21 ? 1 : 0) << 21;
result |= (Category22 ? 1 : 0) << 22;
result |= (Category23 ? 1 : 0) << 23;
result |= (Category24 ? 1 : 0) << 24;
result |= (Category25 ? 1 : 0) << 25;
result |= (Category26 ? 1 : 0) << 26;
result |= (Category27 ? 1 : 0) << 27;
result |= (Category28 ? 1 : 0) << 28;
result |= (Category29 ? 1 : 0) << 29;
result |= (Category30 ? 1 : 0) << 30;
result |= (Category31 ? 1 : 0) << 31;
return unchecked((uint)result);
}
set
{
Category00 = (value & (1 << 0)) != 0;
Category01 = (value & (1 << 1)) != 0;
Category02 = (value & (1 << 2)) != 0;
Category03 = (value & (1 << 3)) != 0;
Category04 = (value & (1 << 4)) != 0;
Category05 = (value & (1 << 5)) != 0;
Category06 = (value & (1 << 6)) != 0;
Category07 = (value & (1 << 7)) != 0;
Category08 = (value & (1 << 8)) != 0;
Category09 = (value & (1 << 9)) != 0;
Category10 = (value & (1 << 10)) != 0;
Category11 = (value & (1 << 11)) != 0;
Category12 = (value & (1 << 12)) != 0;
Category13 = (value & (1 << 13)) != 0;
Category14 = (value & (1 << 14)) != 0;
Category15 = (value & (1 << 15)) != 0;
Category16 = (value & (1 << 16)) != 0;
Category17 = (value & (1 << 17)) != 0;
Category18 = (value & (1 << 18)) != 0;
Category19 = (value & (1 << 19)) != 0;
Category20 = (value & (1 << 20)) != 0;
Category21 = (value & (1 << 21)) != 0;
Category22 = (value & (1 << 22)) != 0;
Category23 = (value & (1 << 23)) != 0;
Category24 = (value & (1 << 24)) != 0;
Category25 = (value & (1 << 25)) != 0;
Category26 = (value & (1 << 26)) != 0;
Category27 = (value & (1 << 27)) != 0;
Category28 = (value & (1 << 28)) != 0;
Category29 = (value & (1 << 29)) != 0;
Category30 = (value & (1 << 30)) != 0;
Category31 = (value & (1 << 31)) != 0;
}
}
public bool Equals(PhysicsCategoryTags other) => Value == other.Value;
public override bool Equals(object obj) => obj is PhysicsCategoryTags other && Equals(other);
public override int GetHashCode() => unchecked((int)Value);
}
}
fileFormatVersion: 2
guid: eddb92a6422c54928b2fb196e49c81d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
interface IPhysicsMaterialProperties
{
CollisionResponsePolicy CollisionResponse { get; set; }
PhysicsMaterialCoefficient Friction { get; set; }
PhysicsMaterialCoefficient Restitution { get; set; }
PhysicsCategoryTags BelongsTo { get; set; }
PhysicsCategoryTags CollidesWith { get; set; }
// TODO: Enable Mass Factors?
// TODO: Surface Velocity?
CustomPhysicsMaterialTags CustomTags { get; set; }
}
interface IInheritPhysicsMaterialProperties : IPhysicsMaterialProperties
{
PhysicsMaterialTemplate Template { get; set; }
bool OverrideCollisionResponse { get; set; }
bool OverrideFriction { get; set; }
bool OverrideRestitution { get; set; }
bool OverrideBelongsTo { get; set; }
bool OverrideCollidesWith { get; set; }
bool OverrideCustomTags { get; set; }
}
[Serializable]
public struct PhysicsMaterialCoefficient
{
[SoftRange(0f, 1f, TextFieldMax = float.MaxValue)]
public float Value;
public Material.CombinePolicy CombineMode;
}
abstract class OverridableValue<T> where T : struct
{
public bool Override { get => m_Override; set => m_Override = value; }
[SerializeField]
bool m_Override;
public T Value
{
get => m_Value;
set
{
m_Value = value;
Override = true;
}
}
[SerializeField]
T m_Value;
public void OnValidate() => OnValidate(ref m_Value);
protected virtual void OnValidate(ref T value) {}
}
[Serializable]
class OverridableCollisionResponse : OverridableValue<CollisionResponsePolicy> {}
[Serializable]
class OverridableMaterialCoefficient : OverridableValue<PhysicsMaterialCoefficient>
{
protected override void OnValidate(ref PhysicsMaterialCoefficient value) =>
value.Value = math.max(0f, value.Value);
}
[Serializable]
class OverridableCategoryTags : OverridableValue<PhysicsCategoryTags> {}
[Serializable]
class OverridableCustomMaterialTags : OverridableValue<CustomPhysicsMaterialTags> {}
[Serializable]
class PhysicsMaterialProperties : IInheritPhysicsMaterialProperties, ISerializationCallbackReceiver
{
public PhysicsMaterialProperties(bool supportsTemplate) => m_SupportsTemplate = supportsTemplate;
[SerializeField, HideInInspector]
bool m_SupportsTemplate;
public PhysicsMaterialTemplate Template
{
get => m_Template;
set => m_Template = m_SupportsTemplate ? value : null;
}
[SerializeField]
[Tooltip("Assign a template to use its values.")]
PhysicsMaterialTemplate m_Template;
static T Get<T>(OverridableValue<T> value, T? templateValue) where T : struct =>
value.Override || templateValue == null ? value.Value : templateValue.Value;
public bool OverrideCollisionResponse { get => m_CollisionResponse.Override; set => m_CollisionResponse.Override = value; }
public CollisionResponsePolicy CollisionResponse
{
get => Get(m_CollisionResponse, m_Template == null ? null : m_Template?.CollisionResponse);
set => m_CollisionResponse.Value = value;
}
[SerializeField]
OverridableCollisionResponse m_CollisionResponse = new OverridableCollisionResponse
{
Value = CollisionResponsePolicy.Collide,
Override = false
};
public bool OverrideFriction { get => m_Friction.Override; set => m_Friction.Override = value; }
public PhysicsMaterialCoefficient Friction
{
get => Get(m_Friction, m_Template == null ? null : m_Template?.Friction);
set => m_Friction.Value = value;
}
[SerializeField]
OverridableMaterialCoefficient m_Friction = new OverridableMaterialCoefficient
{
Value = new PhysicsMaterialCoefficient { Value = 0.5f, CombineMode = Material.CombinePolicy.GeometricMean },
Override = false
};
public bool OverrideRestitution { get => m_Restitution.Override; set => m_Restitution.Override = value; }
public PhysicsMaterialCoefficient Restitution
{
get => Get(m_Restitution, m_Template == null ? null : m_Template?.Restitution);
set => m_Restitution.Value = value;
}
[SerializeField]
OverridableMaterialCoefficient m_Restitution = new OverridableMaterialCoefficient
{
Value = new PhysicsMaterialCoefficient { Value = 0f, CombineMode = Material.CombinePolicy.Maximum },
Override = false
};
public bool OverrideBelongsTo { get => m_BelongsToCategories.Override; set => m_BelongsToCategories.Override = value; }
public PhysicsCategoryTags BelongsTo
{
get => Get(m_BelongsToCategories, m_Template == null ? null : m_Template?.BelongsTo);
set => m_BelongsToCategories.Value = value;
}
[SerializeField]
OverridableCategoryTags m_BelongsToCategories =
new OverridableCategoryTags { Value = PhysicsCategoryTags.Everything, Override = false };
public bool OverrideCollidesWith { get => m_CollidesWithCategories.Override; set => m_CollidesWithCategories.Override = value; }
public PhysicsCategoryTags CollidesWith
{
get => Get(m_CollidesWithCategories, m_Template == null ? null : m_Template?.CollidesWith);
set => m_CollidesWithCategories.Value = value;
}
[SerializeField]
OverridableCategoryTags m_CollidesWithCategories =
new OverridableCategoryTags { Value = PhysicsCategoryTags.Everything, Override = false };
public bool OverrideCustomTags { get => m_CustomMaterialTags.Override; set => m_CustomMaterialTags.Override = value; }
public CustomPhysicsMaterialTags CustomTags
{
get => Get(m_CustomMaterialTags, m_Template == null ? null : m_Template?.CustomTags);
set => m_CustomMaterialTags.Value = value;
}
[SerializeField]
OverridableCustomMaterialTags m_CustomMaterialTags =
new OverridableCustomMaterialTags { Value = default, Override = false };
internal static void OnValidate(ref PhysicsMaterialProperties material, bool supportsTemplate)
{
material.UpgradeVersionIfNecessary();
material.m_SupportsTemplate = supportsTemplate;
if (!supportsTemplate)
{
material.m_Template = null;
material.m_CollisionResponse.Override = true;
material.m_Friction.Override = true;
material.m_Restitution.Override = true;
}
material.m_Friction.OnValidate();
material.m_Restitution.OnValidate();
}
const int k_LatestVersion = 1;
[SerializeField]
int m_SerializedVersion = 0;
void ISerializationCallbackReceiver.OnBeforeSerialize() {}
void ISerializationCallbackReceiver.OnAfterDeserialize() => UpgradeVersionIfNecessary();
internal static bool s_SuppressUpgradeWarnings;
#pragma warning disable 618
void UpgradeVersionIfNecessary()
{
if (m_SerializedVersion < k_LatestVersion)
{
// old data from version < 1 have been removed
if (m_SerializedVersion < 1)
m_SerializedVersion = 1;
}
}
#pragma warning restore 618
}
}
fileFormatVersion: 2
guid: c1e08ac6ebe62466ea40565d8591ae9e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
namespace Unity.Physics.Authoring
{
[CreateAssetMenu(menuName = "Unity Physics/Physics Material Template", fileName = "Physics Material Template", order = 508)]
public sealed class PhysicsMaterialTemplate : ScriptableObject, IPhysicsMaterialProperties
{
PhysicsMaterialTemplate() {}
public CollisionResponsePolicy CollisionResponse { get => m_Value.CollisionResponse; set => m_Value.CollisionResponse = value; }
public PhysicsMaterialCoefficient Friction { get => m_Value.Friction; set => m_Value.Friction = value; }
public PhysicsMaterialCoefficient Restitution { get => m_Value.Restitution; set => m_Value.Restitution = value; }
public PhysicsCategoryTags BelongsTo { get => m_Value.BelongsTo; set => m_Value.BelongsTo = value; }
public PhysicsCategoryTags CollidesWith { get => m_Value.CollidesWith; set => m_Value.CollidesWith = value; }
public CustomPhysicsMaterialTags CustomTags { get => m_Value.CustomTags; set => m_Value.CustomTags = value; }
[SerializeField]
PhysicsMaterialProperties m_Value = new PhysicsMaterialProperties(false);
void Reset() => OnValidate();
void OnValidate() => PhysicsMaterialProperties.OnValidate(ref m_Value, false);
}
}
fileFormatVersion: 2
guid: 79f877434772c463192af154345455c9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: dea88969a14a54552b290b80692e0785, type: 3}
userData:
assetBundleName:
assetBundleVariant:
using UnityEngine;
using Unity.Entities;
using Unity.Physics.GraphicsIntegration;
namespace Unity.Physics.Authoring
{
[AddComponentMenu("Entities/Physics/Physics Render Entity")]
[DisallowMultipleComponent]
public sealed class PhysicsRenderEntityAuthoring : MonoBehaviour
{
[Tooltip("Specifies an Entity in a different branch of the hierarchy that holds the graphical representation of this PhysicsShape.")]
public GameObject RenderEntity;
}
internal class PhysicsRenderEntityBaker : Baker<PhysicsRenderEntityAuthoring>
{
public override void Bake(PhysicsRenderEntityAuthoring authoring)
{
var renderEntity = new PhysicsRenderEntity { Entity = GetEntity(authoring.RenderEntity, TransformUsageFlags.Dynamic) };
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, renderEntity);
}
}
}
fileFormatVersion: 2
guid: ea1d7d5be6993bf4c9c0995e13bf813d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
{
"name": "Unity.Physics.Custom",
"references": [
"Unity.Burst",
"Unity.Collections",
"Unity.Entities",
"Unity.Entities.Hybrid",
"Unity.Mathematics",
"Unity.Physics",
"Unity.Physics.Hybrid",
"Unity.Transforms"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": []
}
fileFormatVersion: 2
guid: 6bfefdf09ee6431fae75a6f5e06a0e89
timeCreated: 1680024908
\ No newline at end of file
fileFormatVersion: 2
guid: d96159b327854bf19d5489084e68fbc3
timeCreated: 1678117648
\ No newline at end of file
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
static partial class PhysicsShapeExtensions
{
static void MakeZAxisPrimaryBasis(ref int3 basisPriority)
{
if (basisPriority[1] == 2)
basisPriority = basisPriority.yxz;
else if (basisPriority[2] == 2)
basisPriority = basisPriority.zxy;
}
#region Box
[BurstCompile]
internal struct BakeBoxJob : IJob
{
public NativeArray<BoxGeometry> Box;
public float4x4 LocalToWorld;
public float4x4 ShapeToWorld;
public EulerAngles Orientation;
public bool BakeUniformScale;
public static float4x4 GetBakeToShape(float4x4 localToWorld, float4x4 shapeToWorld, ref float3 center,
ref EulerAngles orientation, bool bakeUniformScale = true)
{
float4x4 bakeToShape;
float4x4 rotationMatrix = float4x4.identity;
var basisPriority = k_DefaultAxisPriority;
var sheared = localToWorld.HasShear();
if (localToWorld.HasNonUniformScale() || sheared)
{
if (sheared)
{
var transformScale = localToWorld.DecomposeScale();
var basisToWorld =
GetBasisToWorldMatrix(localToWorld, center, orientation, transformScale);
basisPriority = GetBasisAxisPriority(basisToWorld);
}
rotationMatrix = new float4x4(
new float4 { [basisPriority[2]] = 1 },
new float4 { [basisPriority[1]] = 1 },
new float4 { [basisPriority[0]] = 1 },
new float4 { [3] = 1 }
);
}
bakeToShape = GetPrimitiveBakeToShapeMatrix(localToWorld, shapeToWorld, ref center,
ref orientation, 1f, basisPriority, bakeUniformScale);
bakeToShape = math.mul(bakeToShape, rotationMatrix);
return bakeToShape;
}
public void Execute()
{
var center = Box[0].Center;
var size = Box[0].Size;
var bevelRadius = Box[0].BevelRadius;
var bakeToShape = GetBakeToShape(LocalToWorld, ShapeToWorld, ref center, ref Orientation, BakeUniformScale);
bakeToShape = math.mul(bakeToShape, float4x4.Scale(size));
var scale = bakeToShape.DecomposeScale();
size = scale;
Box[0] = new BoxGeometry
{
Center = center,
Orientation = Orientation,
Size = size,
BevelRadius = math.clamp(bevelRadius, 0f, 0.5f * math.cmin(size)),
};
}
}
#endregion
#region Capsule
[BurstCompile]
internal struct BakeCapsuleJob : IJob
{
public NativeArray<CapsuleGeometryAuthoring> Capsule;
public float4x4 LocalToWorld;
public float4x4 ShapeToWorld;
public bool BakeUniformScale;
public static float4x4 GetBakeToShape(float4x4 localToWorld, float4x4 shapeToWorld, ref float3 center,
ref EulerAngles orientation, bool bakeUniformScale = true)
{
var basisPriority = k_DefaultAxisPriority;
var sheared = localToWorld.HasShear();
if (localToWorld.HasNonUniformScale() || sheared)
{
if (sheared)
{
var transformScale = localToWorld.DecomposeScale();
var basisToWorld = GetBasisToWorldMatrix(localToWorld, center, orientation, transformScale);
basisPriority = GetBasisAxisPriority(basisToWorld);
}
MakeZAxisPrimaryBasis(ref basisPriority);
}
return GetPrimitiveBakeToShapeMatrix(localToWorld, shapeToWorld, ref center, ref orientation, 1f,
basisPriority, bakeUniformScale);
}
public void Execute()
{
var radius = Capsule[0].Radius;
var center = Capsule[0].Center;
var height = Capsule[0].Height;
var orientationEuler = Capsule[0].OrientationEuler;
var bakeToShape = GetBakeToShape(LocalToWorld, ShapeToWorld, ref center, ref orientationEuler, BakeUniformScale);
var scale = bakeToShape.DecomposeScale();
radius *= math.cmax(scale.xy);
height = math.max(0, height * scale.z);
Capsule[0] = new CapsuleGeometryAuthoring
{
OrientationEuler = orientationEuler,
Center = center,
Height = height,
Radius = radius
};
}
}
#endregion
#region Cylinder
[BurstCompile]
internal struct BakeCylinderJob : IJob
{
public NativeArray<CylinderGeometry> Cylinder;
public float4x4 LocalToWorld;
public float4x4 ShapeToWorld;
public EulerAngles Orientation;
public bool BakeUniformScale;
public static float4x4 GetBakeToShape(float4x4 localToWorld, float4x4 shapeToWorld, ref float3 center,
ref EulerAngles orientation, bool bakeUniformScale = true)
{
var basisPriority = k_DefaultAxisPriority;
var sheared = localToWorld.HasShear();
if (localToWorld.HasNonUniformScale() || sheared)
{
if (sheared)
{
var transformScale = localToWorld.DecomposeScale();
var basisToWorld = GetBasisToWorldMatrix(localToWorld, center, orientation, transformScale);
basisPriority = GetBasisAxisPriority(basisToWorld);
}
MakeZAxisPrimaryBasis(ref basisPriority);
}
return GetPrimitiveBakeToShapeMatrix(localToWorld, shapeToWorld, ref center, ref orientation, 1f,
basisPriority, bakeUniformScale);
}
public void Execute()
{
var center = Cylinder[0].Center;
var height = Cylinder[0].Height;
var radius = Cylinder[0].Radius;
var bevelRadius = Cylinder[0].BevelRadius;
var bakeToShape = GetBakeToShape(LocalToWorld, ShapeToWorld, ref center, ref Orientation, BakeUniformScale);
var scale = bakeToShape.DecomposeScale();
height *= scale.z;
radius *= math.cmax(scale.xy);
Cylinder[0] = new CylinderGeometry
{
Center = center,
Orientation = Orientation,
Height = height,
Radius = radius,
BevelRadius = math.min(bevelRadius, math.min(height * 0.5f, radius)),
SideCount = Cylinder[0].SideCount
};
}
}
internal static CylinderGeometry BakeToBodySpace(
this CylinderGeometry cylinder, float4x4 localToWorld, float4x4 shapeToWorld, EulerAngles orientation, bool bakeUniformScale = true
)
{
using (var geometry = new NativeArray<CylinderGeometry>(1, Allocator.TempJob) { [0] = cylinder })
{
var job = new BakeCylinderJob
{
Cylinder = geometry,
LocalToWorld = localToWorld,
ShapeToWorld = shapeToWorld,
Orientation = orientation,
BakeUniformScale = bakeUniformScale
};
job.Run();
return geometry[0];
}
}
#endregion
#region Sphere
[BurstCompile]
struct BakeSphereJob : IJob
{
public NativeArray<SphereGeometry> Sphere;
public NativeArray<EulerAngles> Orientation;
public float4x4 LocalToWorld;
public float4x4 ShapeToWorld;
public bool BakeUniformScale;
public void Execute()
{
var center = Sphere[0].Center;
var radius = Sphere[0].Radius;
var orientation = Orientation[0];
var basisToWorld = GetBasisToWorldMatrix(LocalToWorld, center, orientation, 1f);
var basisPriority = basisToWorld.HasShear() ? GetBasisAxisPriority(basisToWorld) : k_DefaultAxisPriority;
var bakeToShape = GetPrimitiveBakeToShapeMatrix(LocalToWorld, ShapeToWorld, ref center, ref orientation, 1f, basisPriority, BakeUniformScale);
radius *= math.cmax(bakeToShape.DecomposeScale());
Sphere[0] = new SphereGeometry
{
Center = center,
Radius = radius
};
Orientation[0] = orientation;
}
}
internal static SphereGeometry BakeToBodySpace(
this SphereGeometry sphere, float4x4 localToWorld, float4x4 shapeToWorld, ref EulerAngles orientation, bool bakeUniformScale = true
)
{
using (var geometry = new NativeArray<SphereGeometry>(1, Allocator.TempJob) { [0] = sphere })
using (var outOrientation = new NativeArray<EulerAngles>(1, Allocator.TempJob) { [0] = orientation })
{
var job = new BakeSphereJob
{
Sphere = geometry,
Orientation = outOrientation,
LocalToWorld = localToWorld,
ShapeToWorld = shapeToWorld,
BakeUniformScale = bakeUniformScale
};
job.Run();
orientation = outOrientation[0];
return geometry[0];
}
}
#endregion
#region Plane
[BurstCompile]
struct BakePlaneJob : IJob
{
public NativeArray<float3x4> Vertices;
public float3 Center;
public float2 Size;
public EulerAngles Orientation;
public float4x4 BakeFromShape;
public void Execute()
{
var v = Vertices[0];
GetPlanePoints(Center, Size, Orientation, out v.c0, out v.c1, out v.c2, out v.c3);
v.c0 = math.mul(BakeFromShape, new float4(v.c0, 1f)).xyz;
v.c1 = math.mul(BakeFromShape, new float4(v.c1, 1f)).xyz;
v.c2 = math.mul(BakeFromShape, new float4(v.c2, 1f)).xyz;
v.c3 = math.mul(BakeFromShape, new float4(v.c3, 1f)).xyz;
Vertices[0] = v;
}
}
internal static void BakeToBodySpace(
float3 center, float2 size, EulerAngles orientation, float4x4 bakeFromShape,
out float3 vertex0, out float3 vertex1, out float3 vertex2, out float3 vertex3
)
{
using (var geometry = new NativeArray<float3x4>(1, Allocator.TempJob))
{
var job = new BakePlaneJob
{
Vertices = geometry,
Center = center,
Size = size,
Orientation = orientation,
BakeFromShape = bakeFromShape
};
job.Run();
vertex0 = geometry[0].c0;
vertex1 = geometry[0].c1;
vertex2 = geometry[0].c2;
vertex3 = geometry[0].c3;
}
}
internal static void GetPlanePoints(
float3 center, float2 size, EulerAngles orientation,
out float3 vertex0, out float3 vertex1, out float3 vertex2, out float3 vertex3
)
{
var sizeYUp = math.float3(size.x, 0, size.y);
vertex0 = center + math.mul(orientation, sizeYUp * math.float3(-0.5f, 0, 0.5f));
vertex1 = center + math.mul(orientation, sizeYUp * math.float3(0.5f, 0, 0.5f));
vertex2 = center + math.mul(orientation, sizeYUp * math.float3(0.5f, 0, -0.5f));
vertex3 = center + math.mul(orientation, sizeYUp * math.float3(-0.5f, 0, -0.5f));
}
#endregion
#region ShapeInputHash
#if !(UNITY_ANDROID && !UNITY_64) // !Android32
// Getting memory alignment errors from HashUtility.Hash128 on Android32
[BurstCompile]
#endif
internal struct GetShapeInputsHashJob : IJob
{
public NativeArray<Hash128> Result;
public uint ForceUniqueIdentifier;
public ConvexHullGenerationParameters GenerationParameters;
public Material Material;
public CollisionFilter CollisionFilter;
public float4x4 BakeFromShape;
[ReadOnly] public NativeArray<HashableShapeInputs> Inputs;
[ReadOnly] public NativeArray<int> AllSkinIndices;
[ReadOnly] public NativeArray<float> AllBlendShapeWeights;
public void Execute()
{
Result[0] = HashableShapeInputs.GetHash128(
ForceUniqueIdentifier, GenerationParameters, Material, CollisionFilter, BakeFromShape,
Inputs, AllSkinIndices, AllBlendShapeWeights
);
}
}
#endregion
#region AABB
[BurstCompile]
internal struct GetAabbJob : IJob
{
[ReadOnly] public NativeArray<float3> Points;
public NativeArray<Aabb> Aabb;
public void Execute()
{
var aabb = new Aabb { Min = float.MaxValue, Max = float.MinValue };
for (var i = 0; i < Points.Length; ++i)
aabb.Include(Points[i]);
Aabb[0] = aabb;
}
}
#endregion
}
}
fileFormatVersion: 2
guid: c1d2f87b6ade497cb1e74c86f2831579
timeCreated: 1678214783
\ No newline at end of file
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
static partial class PhysicsShapeExtensions
{
public static class BakeBoxJobExtension
{
internal static float4x4 GetBakeToShape(PhysicsShapeAuthoring shape, float3 center, EulerAngles orientation)
{
var transform = shape.transform;
var localToWorld = (float4x4)transform.localToWorldMatrix;
var shapeToWorld = shape.GetShapeToWorldMatrix();
return BakeBoxJob.GetBakeToShape(localToWorld, shapeToWorld, ref center, ref orientation);
}
}
public static class BakeCapsuleJobExtension
{
internal static float4x4 GetBakeToShape(PhysicsShapeAuthoring shape, float3 center, EulerAngles orientation)
{
var transform = shape.transform;
var localToWorld = (float4x4)transform.localToWorldMatrix;
var shapeToWorld = shape.GetShapeToWorldMatrix();
return BakeCapsuleJob.GetBakeToShape(localToWorld, shapeToWorld, ref center,
ref orientation);
}
}
public static void SetBakedCapsuleSize(this PhysicsShapeAuthoring shape, float height, float radius)
{
var capsule = shape.GetCapsuleProperties();
var center = capsule.Center;
var bakeToShape = BakeCapsuleJobExtension.GetBakeToShape(shape, center, capsule.OrientationEuler);
var scale = bakeToShape.DecomposeScale();
var newRadius = radius / math.cmax(scale.xy);
if (math.abs(capsule.Radius - newRadius) > kMinimumChange)
capsule.Radius = newRadius;
height /= scale.z;
if (math.abs(math.length(capsule.Height - height)) > kMinimumChange)
capsule.Height = height;
shape.SetCapsule(capsule);
}
internal static CapsuleGeometryAuthoring BakeToBodySpace(
this CapsuleGeometryAuthoring capsule, float4x4 localToWorld, float4x4 shapeToWorld, bool bakeUniformScale = true
)
{
using (var geometry = new NativeArray<CapsuleGeometryAuthoring>(1, Allocator.TempJob) { [0] = capsule })
{
var job = new BakeCapsuleJob
{
Capsule = geometry,
LocalToWorld = localToWorld,
ShapeToWorld = shapeToWorld,
BakeUniformScale = bakeUniformScale
};
job.Run();
return geometry[0];
}
}
public static class BakeCylinderJobExtension
{
internal static float4x4 GetBakeToShape(PhysicsShapeAuthoring shape, float3 center, EulerAngles orientation)
{
var transform = shape.transform;
var localToWorld = (float4x4)transform.localToWorldMatrix;
var shapeToWorld = shape.GetShapeToWorldMatrix();
return BakeCylinderJob.GetBakeToShape(localToWorld, shapeToWorld, ref center,
ref orientation);
}
}
public static CylinderGeometry GetBakedCylinderProperties(this PhysicsShapeAuthoring shape)
{
var cylinder = shape.GetCylinderProperties(out var orientation);
return cylinder.BakeToBodySpace(shape.transform.localToWorldMatrix, shape.GetShapeToWorldMatrix(),
orientation);
}
public static void SetBakedSphereRadius(this PhysicsShapeAuthoring shape, float radius)
{
var sphere = shape.GetSphereProperties(out EulerAngles eulerAngles);
var center = sphere.Center;
radius = math.abs(radius);
var basisToWorld = GetBasisToWorldMatrix(shape.transform.localToWorldMatrix, center, eulerAngles, 1f);
var basisPriority = basisToWorld.HasShear() ? GetBasisAxisPriority(basisToWorld) : k_DefaultAxisPriority;
var bakeToShape = GetPrimitiveBakeToShapeMatrix(shape.transform.localToWorldMatrix, shape.GetShapeToWorldMatrix(), ref center, ref eulerAngles, 1f, basisPriority);
var scale = math.cmax(bakeToShape.DecomposeScale());
var newRadius = radius / scale;
sphere.Radius = newRadius;
shape.SetSphere(sphere);
}
public static void SetBakedPlaneSize(this PhysicsShapeAuthoring shape, float2 size)
{
shape.GetPlaneProperties(out var center, out var planeSize, out EulerAngles orientation);
var prevSize = math.abs(planeSize);
size = math.abs(size);
if (math.abs(size[0] - prevSize[0]) < kMinimumChange) size[0] = prevSize[0];
if (math.abs(size[1] - prevSize[1]) < kMinimumChange) size[1] = prevSize[1];
planeSize = size;
shape.SetPlane(center, planeSize, orientation);
}
}
}
fileFormatVersion: 2
guid: 20e0be4d61f647dfaa267fda69e86818
timeCreated: 1678218998
\ No newline at end of file
using System;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
/// <summary>
/// A structure for storing authoring data for a capsule shape. In contrast to the
/// CapsuleGeometry struct in the run-time, this structure permits storing stable orientation
/// values, as well as height values that can be retained when the source data are defined with
/// respect to a non-uniformly scaled object.
/// </summary>
[Serializable]
public struct CapsuleGeometryAuthoring : IEquatable<CapsuleGeometryAuthoring>
{
/// <summary>
/// The local orientation of the capsule. It is aligned with the forward axis (z) when it is
/// identity.
/// </summary>
public quaternion Orientation { get => m_OrientationEuler; set => m_OrientationEuler.SetValue(value); }
internal EulerAngles OrientationEuler { get => m_OrientationEuler; set => m_OrientationEuler = value; }
[SerializeField]
EulerAngles m_OrientationEuler;
/// <summary> The local position offset of the capsule. </summary>
public float3 Center { get => m_Center; set => m_Center = value; }
[SerializeField]
float3 m_Center;
/// <summary>
/// The height of the capsule. It may store any value, but will ultimately always be converted
/// into a value that is at least twice the radius.
/// </summary>
public float Height { get => m_Height; set => m_Height = value; }
[SerializeField]
float m_Height;
/// <summary> The radius of the capsule. </summary>
///
/// <value> The radius. </value>
public float Radius { get => m_Radius; set => m_Radius = value; }
[SerializeField]
float m_Radius;
public bool Equals(CapsuleGeometryAuthoring other)
{
return m_Height.Equals(other.m_Height)
&& m_Center.Equals(other.m_Center)
&& m_Radius.Equals(other.m_Radius)
&& m_OrientationEuler.Equals(other.m_OrientationEuler);
}
public override int GetHashCode()
{
return unchecked((int)math.hash(
new float3x3(
Center,
m_OrientationEuler.Value,
new float3((float)m_OrientationEuler.RotationOrder, m_Height, m_Radius)
)
));
}
}
public static class CapsuleGeometryAuthoringExtensions
{
/// <summary>
/// Construct a CapsuleGeometryAuthoring instance from a run-time CapsuleGeometry instance.
/// </summary>
public static CapsuleGeometryAuthoring ToAuthoring(this CapsuleGeometry input)
{
var orientationEuler = EulerAngles.Default;
orientationEuler.SetValue(quaternion.LookRotationSafe(input.Vertex1 - input.Vertex0, math.up()));
return new CapsuleGeometryAuthoring
{
Height = input.GetHeight(),
OrientationEuler = orientationEuler,
Center = input.GetCenter(),
Radius = input.Radius
};
}
/// <summary>
/// Construct a run-time CapsuleGeometry instance from a CapsuleGeometryAuthoring instance.
/// </summary>
public static CapsuleGeometry ToRuntime(this CapsuleGeometryAuthoring input)
{
var halfHeight = 0.5f * input.Height;
var halfDistance = halfHeight - input.Radius;
var axis = math.normalize(math.mul(input.Orientation, new float3 { z = 1f }));
var halfAxis = axis * halfDistance;
var vertex0 = input.Center + halfAxis;
var vertex1 = input.Center - halfAxis;
return new CapsuleGeometry
{
Vertex0 = vertex0,
Vertex1 = vertex1,
Radius = input.Radius
};
}
}
}
fileFormatVersion: 2
guid: 4df9a1d1ba0ee8a45acfdc75585997fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Collections;
using Unity.Mathematics;
namespace Unity.Physics.Authoring
{
public static class ConvexHullGenerationParametersExtensions
{
// recommended simplification tolerance is at least 1 centimeter
internal const float k_MinRecommendedSimplificationTolerance = 0.01f;
internal static void InitializeToRecommendedAuthoringValues(
ref this ConvexHullGenerationParameters generationParameters, NativeArray<float3> points
)
{
generationParameters = ConvexHullGenerationParameters.Default.ToAuthoring();
if (points.Length <= 1)
return;
var bounds = new Aabb { Min = points[0], Max = points[0] };
for (var i = 1; i < points.Length; ++i)
bounds.Include(points[i]);
generationParameters.SimplificationTolerance = math.max(
k_MinRecommendedSimplificationTolerance,
ConvexHullGenerationParameters.Default.SimplificationTolerance * math.cmax(bounds.Extents)
);
// TODO: initialize other properties based on input points?
}
internal static void OnValidate(ref this ConvexHullGenerationParameters generationParameters, float maxAngle = 180f)
{
generationParameters.SimplificationTolerance = math.max(0f, generationParameters.SimplificationTolerance);
generationParameters.BevelRadius = math.max(0f, generationParameters.BevelRadius);
generationParameters.MinimumAngle = math.clamp(generationParameters.MinimumAngle, 0f, maxAngle);
}
public static ConvexHullGenerationParameters ToAuthoring(this ConvexHullGenerationParameters generationParameters)
{
generationParameters.MinimumAngle = math.degrees(generationParameters.MinimumAngle);
return generationParameters;
}
public static ConvexHullGenerationParameters ToRunTime(this ConvexHullGenerationParameters generationParameters)
{
generationParameters.MinimumAngle = math.radians(generationParameters.MinimumAngle);
return generationParameters;
}
}
}
fileFormatVersion: 2
guid: 604da30f59bed4d458c29f4c359d7f1c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
[Serializable]
internal struct EulerAngles : IEquatable<EulerAngles>
{
public static EulerAngles Default => new EulerAngles { RotationOrder = math.RotationOrder.ZXY };
public float3 Value;
[HideInInspector]
public math.RotationOrder RotationOrder;
internal void SetValue(quaternion value) => Value = math.degrees(Math.ToEulerAngles(value, RotationOrder));
public static implicit operator quaternion(EulerAngles euler) =>
math.normalize(quaternion.Euler(math.radians(euler.Value), euler.RotationOrder));
public bool Equals(EulerAngles other) => Value.Equals(other.Value) && RotationOrder == other.RotationOrder;
public override bool Equals(object obj) => obj is EulerAngles other && Equals(other);
public override int GetHashCode() => unchecked((int)math.hash(new float4(Value, (float)RotationOrder)));
}
}
fileFormatVersion: 2
guid: 140e4ed2e13547ac8c8eb623bd5fc90a
timeCreated: 1581282000
\ No newline at end of file
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityComponent = UnityEngine.Component;
namespace Unity.Physics.Authoring
{
public struct GetActiveChildrenScope<T> : IDisposable where T : UnityComponent
{
static readonly List<PhysicsShapeAuthoring> s_PhysicsShapes = new List<PhysicsShapeAuthoring>(8);
static bool s_BufferUsed;
static List<T> s_Buffer = new List<T>(8);
public List<T> Buffer => m_Disposed ? null : s_Buffer;
bool m_Disposed;
PhysicsShapeAuthoring m_Shape;
Transform m_Root;
GameObject m_PrimaryBody;
bool m_CheckIfComponentBelongsToShape;
public GetActiveChildrenScope(PhysicsShapeAuthoring shape, Transform root)
{
m_Disposed = false;
m_Shape = shape;
m_Root = root;
m_PrimaryBody = PhysicsShapeExtensions.GetPrimaryBody(root.gameObject);
m_CheckIfComponentBelongsToShape = root.transform.IsChildOf(shape.transform);
if (s_BufferUsed)
throw new InvalidOperationException($"Cannot nest two {GetType()}");
s_BufferUsed = true;
root.GetComponentsInChildren(true, s_Buffer);
}
public void Dispose()
{
if (m_Disposed)
return;
m_Disposed = true;
s_BufferUsed = false;
s_Buffer.Clear();
}
public bool IsChildActiveAndBelongsToShape(T child, bool filterOutInvalid = true)
{
var meshFilter = (UnityComponent)child as MeshFilter;
if (meshFilter != null)
{
if (meshFilter.sharedMesh == null)
return false;
var renderer = meshFilter.GetComponent<MeshRenderer>();
if (renderer == null || !renderer.enabled)
return false;
if (filterOutInvalid && !meshFilter.sharedMesh.IsValidForConversion(m_Shape.gameObject))
return false;
}
if (m_CheckIfComponentBelongsToShape)
{
if (PhysicsShapeExtensions.GetPrimaryBody(child.gameObject) != m_PrimaryBody)
return false;
child.gameObject.GetComponentsInParent(true, s_PhysicsShapes);
if (s_PhysicsShapes[0] != m_Shape)
{
s_PhysicsShapes.Clear();
return false;
}
}
// do not simply use GameObject.activeInHierarchy because it will be false when instantiating a prefab
var t = child.transform;
var activeInHierarchy = t.gameObject.activeSelf;
while (activeInHierarchy && t != m_Root)
{
t = t.parent;
activeInHierarchy &= t.gameObject.activeSelf;
}
return activeInHierarchy;
}
}
}
fileFormatVersion: 2
guid: e4bd7be6158804ad69909cce096724d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
namespace Unity.Physics.Authoring
{
// put static UnityObject buffers in separate utility class so other methods can Burst compile
static class PhysicsShapeExtensions_NonBursted
{
internal static readonly List<PhysicsBodyAuthoring> s_PhysicsBodiesBuffer = new List<PhysicsBodyAuthoring>(16);
internal static readonly List<PhysicsShapeAuthoring> s_ShapesBuffer = new List<PhysicsShapeAuthoring>(16);
internal static readonly List<Rigidbody> s_RigidbodiesBuffer = new List<Rigidbody>(16);
internal static readonly List<UnityEngine.Collider> s_CollidersBuffer = new List<UnityEngine.Collider>(16);
}
public static partial class PhysicsShapeExtensions
{
// used for de-skewing basis vectors; default priority assumes primary axis is z, secondary axis is y
public static readonly int3 k_DefaultAxisPriority = new int3(2, 1, 0);
// avoids drift in axes we're not actually changing
public const float kMinimumChange = HashableShapeInputs.k_DefaultLinearPrecision;
static readonly int[] k_NextAxis = { 1, 2, 0 };
static readonly int[] k_PrevAxis = { 2, 0, 1 };
// matrix to transform point from shape's local basis into world space
public static float4x4 GetBasisToWorldMatrix(
float4x4 localToWorld, float3 center, quaternion orientation, float3 size
) =>
math.mul(localToWorld, float4x4.TRS(center, orientation, size));
static float4 DeskewSecondaryAxis(float4 primaryAxis, float4 secondaryAxis)
{
var n0 = math.normalizesafe(primaryAxis);
var dot = math.dot(secondaryAxis, n0);
return secondaryAxis - n0 * dot;
}
// priority is determined by length of each size dimension in the shape's basis after applying localToWorld transformation
public static int3 GetBasisAxisPriority(float4x4 basisToWorld)
{
var basisAxisLengths = basisToWorld.DecomposeScale();
var max = math.cmax(basisAxisLengths);
var min = math.cmin(basisAxisLengths);
if (max == min)
return k_DefaultAxisPriority;
var imax = max == basisAxisLengths.x ? 0 : max == basisAxisLengths.y ? 1 : 2;
basisToWorld[k_NextAxis[imax]] = DeskewSecondaryAxis(basisToWorld[imax], basisToWorld[k_NextAxis[imax]]);
basisToWorld[k_PrevAxis[imax]] = DeskewSecondaryAxis(basisToWorld[imax], basisToWorld[k_PrevAxis[imax]]);
basisAxisLengths = basisToWorld.DecomposeScale();
min = math.cmin(basisAxisLengths);
var imin = min == basisAxisLengths.x ? 0 : min == basisAxisLengths.y ? 1 : 2;
if (imin == imax)
imin = k_NextAxis[imax];
var imid = k_NextAxis[imax] == imin ? k_PrevAxis[imax] : k_NextAxis[imax];
return new int3(imax, imid, imin);
}
[Conditional(CompilationSymbols.CollectionsChecksSymbol), Conditional(CompilationSymbols.DebugChecksSymbol)]
static void CheckBasisPriorityAndThrow(int3 basisPriority)
{
if (
basisPriority.x == basisPriority.y
|| basisPriority.x == basisPriority.z
|| basisPriority.y == basisPriority.z
)
throw new ArgumentException(nameof(basisPriority));
}
// matrix to transform point on a primitive from bake space into space of the shape
internal static float4x4 GetPrimitiveBakeToShapeMatrix(
float4x4 localToWorld, float4x4 shapeToWorld, ref float3 center, ref EulerAngles orientation, float3 scale, int3 basisPriority, bool bakeUniformScale = true
)
{
CheckBasisPriorityAndThrow(basisPriority);
var localToBasis = float4x4.TRS(center, orientation, scale);
// correct for imprecision in cases of no scale to prevent e.g., convex radius from being altered
if (scale.Equals(new float3(1f)))
{
localToBasis.c0 = math.normalizesafe(localToBasis.c0);
localToBasis.c1 = math.normalizesafe(localToBasis.c1);
localToBasis.c2 = math.normalizesafe(localToBasis.c2);
}
float4x4 bakeToShape;
if (localToWorld.HasNonUniformScale() || localToWorld.HasShear())
{
var localToBake = math.mul(localToWorld, localToBasis);
// deskew second longest axis with respect to longest axis
localToBake[basisPriority[1]] =
DeskewSecondaryAxis(localToBake[basisPriority[0]], localToBake[basisPriority[1]]);
// recompute third axes from first two
var n2 = math.normalizesafe(
new float4(math.cross(localToBake[basisPriority[0]].xyz, localToBake[basisPriority[1]].xyz), 0f)
);
localToBake[basisPriority[2]] = n2 * math.dot(localToBake[basisPriority[2]], n2);
bakeToShape = math.mul(math.inverse(shapeToWorld), localToBake);
}
else
{
if (bakeUniformScale)
{
var localToBake = math.mul(localToWorld, localToBasis);
bakeToShape = math.mul(math.inverse(shapeToWorld), localToBake);
}
else
{
bakeToShape = localToBasis;
}
}
// transform baked center/orientation (i.e. primitive basis) into shape space
orientation.SetValue(
quaternion.LookRotationSafe(bakeToShape[basisPriority[0]].xyz, bakeToShape[basisPriority[1]].xyz)
);
center = bakeToShape.c3.xyz;
return bakeToShape;
}
internal static CollisionFilter GetFilter(this PhysicsShapeAuthoring shape)
{
// TODO: determine optimal workflow for specifying group index
return new CollisionFilter
{
BelongsTo = shape.BelongsTo.Value,
CollidesWith = shape.CollidesWith.Value
};
}
internal static Material GetMaterial(this PhysicsShapeAuthoring shape)
{
// TODO: TBD how we will author editor content for other shape flags
return new Material
{
Friction = shape.Friction.Value,
FrictionCombinePolicy = shape.Friction.CombineMode,
Restitution = shape.Restitution.Value,
RestitutionCombinePolicy = shape.Restitution.CombineMode,
CollisionResponse = shape.CollisionResponse,
CustomTags = shape.CustomTags.Value
};
}
public static GameObject FindTopmostEnabledAncestor<T>(GameObject shape, List<T> buffer) where T : Component
{
// include inactive in case the supplied shape GameObject is a prefab that has not been instantiated
shape.GetComponentsInParent(true, buffer);
GameObject result = null;
for (var i = buffer.Count - 1; i >= 0; --i)
{
if (
(buffer[i] as UnityEngine.Collider)?.enabled ??
(buffer[i] as MonoBehaviour)?.enabled ?? true
)
{
result = buffer[i].gameObject;
break;
}
}
buffer.Clear();
return result;
}
public static GameObject GetPrimaryBody(this PhysicsShapeAuthoring shape) => GetPrimaryBody(shape.gameObject);
public static GameObject GetPrimaryBody(GameObject shape)
{
var pb = ColliderExtensions.FindFirstEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_PhysicsBodiesBuffer);
var rb = ColliderExtensions.FindFirstEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_RigidbodiesBuffer);
if (pb != null)
{
return rb == null ? pb.gameObject :
pb.transform.IsChildOf(rb.transform) ? pb.gameObject : rb.gameObject;
}
if (rb != null)
return rb.gameObject;
// for implicit static shape, first see if it is part of static optimized hierarchy
ColliderExtensions.FindTopmostStaticEnabledAncestor(shape, out GameObject topStatic);
if (topStatic != null)
return topStatic;
// otherwise, find topmost enabled Collider or PhysicsShapeAuthoring
var topCollider = FindTopmostEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_CollidersBuffer);
var topShape = FindTopmostEnabledAncestor(shape, PhysicsShapeExtensions_NonBursted.s_ShapesBuffer);
return topCollider == null
? topShape == null ? shape.gameObject : topShape
: topShape == null
? topCollider
: topShape.transform.IsChildOf(topCollider.transform)
? topCollider
: topShape;
}
public static BoxGeometry GetBakedBoxProperties(this PhysicsShapeAuthoring shape)
{
var box = shape.GetBoxProperties(out var orientation);
return box.BakeToBodySpace(shape.transform.localToWorldMatrix, shape.GetShapeToWorldMatrix(), orientation);
}
internal static BoxGeometry BakeToBodySpace(
this BoxGeometry box, float4x4 localToWorld, float4x4 shapeToWorld, EulerAngles orientation, bool bakeUniformScale = true
)
{
using (var geometry = new NativeArray<BoxGeometry>(1, Allocator.TempJob) { [0] = box })
{
var job = new BakeBoxJob
{
Box = geometry,
LocalToWorld = localToWorld,
ShapeToWorld = shapeToWorld,
Orientation = orientation,
BakeUniformScale = bakeUniformScale
};
job.Run();
return geometry[0];
}
}
public static void SetBakedBoxSize(this PhysicsShapeAuthoring shape, float3 size, float bevelRadius)
{
var box = shape.GetBoxProperties(out var orientation);
var center = box.Center;
var prevSize = math.abs(box.Size);
size = math.abs(size);
var bakeToShape = BakeBoxJobExtension.GetBakeToShape(shape, center, orientation);
var scale = bakeToShape.DecomposeScale();
size /= scale;
if (math.abs(size[0] - prevSize[0]) < kMinimumChange) size[0] = prevSize[0];
if (math.abs(size[1] - prevSize[1]) < kMinimumChange) size[1] = prevSize[1];
if (math.abs(size[2] - prevSize[2]) < kMinimumChange) size[2] = prevSize[2];
box.BevelRadius = bevelRadius;
box.Size = size;
shape.SetBox(box, orientation);
}
internal static CapsuleGeometryAuthoring GetBakedCapsuleProperties(this PhysicsShapeAuthoring shape)
{
var capsule = shape.GetCapsuleProperties();
return capsule.BakeToBodySpace(shape.transform.localToWorldMatrix, shape.GetShapeToWorldMatrix());
}
public static void SetBakedCylinderSize(this PhysicsShapeAuthoring shape, float height, float radius, float bevelRadius)
{
var cylinder = shape.GetCylinderProperties(out EulerAngles orientation);
var center = cylinder.Center;
var bakeToShape = BakeCylinderJobExtension.GetBakeToShape(shape, center, orientation);
var scale = bakeToShape.DecomposeScale();
var newRadius = radius / math.cmax(scale.xy);
if (math.abs(cylinder.Radius - newRadius) > kMinimumChange) cylinder.Radius = newRadius;
if (math.abs(cylinder.BevelRadius - bevelRadius) > kMinimumChange) cylinder.BevelRadius = bevelRadius;
var newHeight = math.max(0, height / scale.z);
if (math.abs(cylinder.Height - newHeight) > kMinimumChange) cylinder.Height = newHeight;
shape.SetCylinder(cylinder, orientation);
}
internal static SphereGeometry GetBakedSphereProperties(this PhysicsShapeAuthoring shape, out EulerAngles orientation)
{
var sphere = shape.GetSphereProperties(out orientation);
return sphere.BakeToBodySpace(shape.transform.localToWorldMatrix, shape.GetShapeToWorldMatrix(), ref orientation);
}
internal static void GetBakedPlaneProperties(
this PhysicsShapeAuthoring shape, out float3 vertex0, out float3 vertex1, out float3 vertex2, out float3 vertex3
)
{
var bakeToShape = shape.GetLocalToShapeMatrix();
shape.GetPlaneProperties(out var center, out var size, out EulerAngles orientation);
BakeToBodySpace(
center, size, orientation, bakeToShape,
out vertex0, out vertex1, out vertex2, out vertex3
);
}
public static void GetBakedConvexProperties(this PhysicsShapeAuthoring shape, NativeList<float3> pointCloud)
{
shape.GetConvexHullProperties(pointCloud, true, default, default, default, default);
shape.BakePoints(pointCloud.AsArray());
}
public static void GetBakedMeshProperties(
this PhysicsShapeAuthoring shape, NativeList<float3> vertices, NativeList<int3> triangles,
HashSet<UnityEngine.Mesh> meshAssets = null
)
{
shape.GetMeshProperties(vertices, triangles, true, default, meshAssets);
shape.BakePoints(vertices.AsArray());
}
const float k_HashFloatTolerance = 0.01f;
// used to hash convex hull generation properties in a way that is robust to imprecision
public static uint GetStableHash(
this ConvexHullGenerationParameters generationParameters,
ConvexHullGenerationParameters hashedParameters,
float tolerance = k_HashFloatTolerance
)
{
var differences = new float3(
generationParameters.BevelRadius - hashedParameters.BevelRadius,
generationParameters.MinimumAngle - hashedParameters.MinimumAngle,
generationParameters.SimplificationTolerance - hashedParameters.SimplificationTolerance
);
return math.cmax(math.abs(differences)) < tolerance
? unchecked((uint)hashedParameters.GetHashCode())
: unchecked((uint)generationParameters.GetHashCode());
}
// used to hash an array of points in a way that is robust to imprecision
public static unsafe uint GetStableHash(
this NativeList<float3> points, NativeArray<float3> hashedPoints, float tolerance = k_HashFloatTolerance
)
{
if (points.Length != hashedPoints.Length)
return math.hash(points.GetUnsafePtr(), UnsafeUtility.SizeOf<float3>() * points.Length);
for (int i = 0, count = points.Length; i < count; ++i)
{
if (math.cmax(math.abs(points[i] - hashedPoints[i])) > tolerance)
return math.hash(points.GetUnsafePtr(), UnsafeUtility.SizeOf<float3>() * points.Length);
}
return math.hash(hashedPoints.GetUnsafePtr(), UnsafeUtility.SizeOf<float3>() * hashedPoints.Length);
}
public static int GetMaxAxis(this float3 v)
{
var cmax = math.cmax(v);
return cmax == v.z ? 2 : cmax == v.y ? 1 : 0;
}
public static int GetDeviantAxis(this float3 v)
{
var deviation = math.abs(v - math.csum(v) / 3f);
return math.cmax(deviation) == deviation.z ? 2 : math.cmax(deviation) == deviation.y ? 1 : 0;
}
}
}
fileFormatVersion: 2
guid: 748b14f16118437d8c102dec4473353b
timeCreated: 1678131109
\ No newline at end of file
using UnityEngine;
namespace Unity.Physics.Authoring
{
sealed class EnumFlagsAttribute : PropertyAttribute {}
sealed class ExpandChildrenAttribute : PropertyAttribute {}
sealed class SoftRangeAttribute : PropertyAttribute
{
public readonly float SliderMin;
public readonly float SliderMax;
public float TextFieldMin { get; set; }
public float TextFieldMax { get; set; }
public SoftRangeAttribute(float min, float max)
{
SliderMin = TextFieldMin = min;
SliderMax = TextFieldMax = max;
}
}
}
fileFormatVersion: 2
guid: d0db1130e6fc44abea606b6aefc06d82
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: abd30ee0214cf6a45b2d76765a4615b1, type: 3}
m_Name: NetCodeConfig
m_EditorClassIdentifier:
IsGlobalConfig: 0
EnableClientServerBootstrap: 1
ClientServerTickRate:
SimulationTickRate: 60
PredictedFixedStepSimulationTickRatio: 1
NetworkTickRate: 0
MaxSimulationStepsPerFrame: 1
MaxSimulationStepBatchSize: 4
TargetFrameRateMode: 0
m_SendSnapshotsForCatchUpTicks: 0
SnapshotAckMaskCapacity: 4096
HandshakeApprovalTimeoutMS: 5000
ClientTickRate:
InterpolationTimeNetTicks: 2
InterpolationTimeMS: 0
MaxExtrapolationTimeSimTicks: 20
MaxPredictAheadTimeMS: 500
TargetCommandSlack: 2
NumAdditionalCommandsToSend: 2
MaxPredictionStepBatchSizeRepeatedTick: 0
MaxPredictionStepBatchSizeFirstTimeTick: 0
PredictionLoopUpdateMode: 0
InterpolationDelayJitterScale: 1.25
InterpolationDelayMaxDeltaTicksFraction: 0.1
InterpolationDelayCorrectionFraction: 0.1
InterpolationTimeScaleMin: 0.85
InterpolationTimeScaleMax: 1.1
CommandAgeCorrectionFraction: 0.1
PredictionTimeScaleMin: 0.9
PredictionTimeScaleMax: 1.1
GhostSendSystemData:
DefaultSnapshotPacketSize: 0
MinSendImportance: 0
MinDistanceScaledSendImportance: 0
MaxIterateChunks: 0
MaxSendChunks: 0
MaxSendEntities: 0
m_ForceSingleBaseline: 0
m_ForcePreSerialize: 0
m_KeepSnapshotHistoryOnStructuralChange: 1
m_EnablePerComponentProfiling: 0
CleanupConnectionStatePerTick: 1
m_FirstSendImportanceMultiplier: 1
m_IrrelevantImportanceDownScale: 1
m_TempStreamSize: 8192
m_UseCustomSerializer: 0
ConnectTimeoutMS: 1000
MaxConnectAttempts: 60
DisconnectTimeoutMS: 30000
HeartbeatTimeoutMS: 500
ReconnectionTimeoutMS: 2000
ClientSendQueueCapacity: 64
ClientReceiveQueueCapacity: 64
ServerSendQueueCapacity: 512
ServerReceiveQueueCapacity: 512
MaxMessageSize: 1400
fileFormatVersion: 2
guid: cd69de227738309429193c9089949c16
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: cea4b49c4d6784a3291bea84d8086c8e, type: 3}
m_Name: Physics Category Names
m_EditorClassIdentifier:
m_CategoryNames:
- Terrain
- Player
- Enemy
- Projectiles
- Structures
- Raycasts
- TargetCasts
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
fileFormatVersion: 2
guid: 55a8f0cd0632c1848a96adc76d75ff94
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 30d685c2d5384d24a8b58bcfe1eed469
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 383b8acbdeeb36f45805802bf80f9774
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:
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
importPhysicalCameras: 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:
fileFormatVersion: 2
guid: 0b25e149dd9ab7b4299854c51b044498
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 670a7e7fd4e80a349bb9fe6e37875239
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 13e6a6cab1dbefa4881feb540cbd897e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 54055e963725d3946b0f8ecd5aff2954
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -19,9 +19,3 @@ public class CameraFollowAuthoring : MonoBehaviour
}
}
}
public struct CameraFollow : IComponentData
{
public Entity PlayerEntity;
public float3 Offset;
}
\ No newline at end of file
fileFormatVersion: 2
guid: 7662c27eaacab63408f86c4f228498e7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using UnityEngine;
public class HitPointsAuthoring : MonoBehaviour
{
public int MaxHitPoints;
// public Vector3 HealthBarOffset;
public class HitPointsBaker : Baker<HitPointsAuthoring>
{
public override void Bake(HitPointsAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new CurrentHitPoints { Value = authoring.MaxHitPoints });
AddComponent(entity, new MaxHitPoints { Value = authoring.MaxHitPoints });
AddBuffer<DamageBufferElement>(entity);
AddBuffer<DamageThisTick>(entity);
//AddComponent(entity, new HealthBarOffset { Value = authoring.HealthBarOffset });
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 8e73c985659b81d408f4e99cb152349d
\ No newline at end of file
using Unity.Entities;
using UnityEngine;
public class TeamAuthoring : MonoBehaviour
{
public TeamType TeamType;
public class TeamBaker : Baker<TeamAuthoring>
{
public override void Bake(TeamAuthoring authoring)
{
//transform.none?
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new TeamTypes { Value = authoring.TeamType });
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 8b4cd120b33db8143be607a7d5012817
\ No newline at end of file
fileFormatVersion: 2
guid: 6715bbdf30aa4904482eb6b69739d1c7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using UnityEngine;
public class AbilityMoveSpeedAuthoring : MonoBehaviour
{
public float AbilityMoveSpeed;
public class AbilityMoveSpeedBaker : Baker<AbilityMoveSpeedAuthoring>
{
public override void Bake(AbilityMoveSpeedAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new AbilityMoveSpeed { Value = authoring.AbilityMoveSpeed });
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 1f03a841418196747bbd25842c79de4f
\ No newline at end of file
using Unity.Entities;
using UnityEngine;
public class DamageOnTriggerAuthoring : MonoBehaviour
{
public int DamageOnTrigger;
public class DamageOnTriggerBaker : Baker<DamageOnTriggerAuthoring>
{
public override void Bake(DamageOnTriggerAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new DamageOnTrigger { Value = authoring.DamageOnTrigger });
AddBuffer<AlreadyDamagedEntity>(entity);
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 2de495c310a322143be08aa7819a1a33
\ No newline at end of file
using Unity.Entities;
using UnityEngine;
public class DestroyOnTimerAuthoring : MonoBehaviour
{
public float DestroyOnTimer;
public class DestroyOnTimerBaker : Baker<DestroyOnTimerAuthoring>
{
public override void Bake(DestroyOnTimerAuthoring authoring)
{
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new DestroyOnTimer() { Value = authoring.DestroyOnTimer });
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 7e19d579a4586dd40805276eb2d1a684
\ No newline at end of file
using Unity.Entities;
using Unity.NetCode;
using UnityEngine;
public class NpcAttackAuthoring : MonoBehaviour
{
public float NpcTargetRadius;
public float AttackCooldownTime;
public Vector3 FirePointOffset;
public GameObject AttackPrefab;
public NetCodeConfig NetCodeConfig;
public int SimulationTickRate => NetCodeConfig.ClientServerTickRate.SimulationTickRate;
public class NpcAttackBaker : Baker<NpcAttackAuthoring>
{
public override void Bake(NpcAttackAuthoring authoring)
{
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
AddComponent(entity, new NpcTargetRadius { Value = authoring.NpcTargetRadius });
AddComponent(entity, new NpcAttackProperties
{
FirePointOffset = authoring.FirePointOffset,
CooldownTickCount = (uint)(authoring.AttackCooldownTime * authoring.SimulationTickRate),
AttackPrefab = GetEntity(authoring.AttackPrefab, TransformUsageFlags.Dynamic)
});
AddComponent<NpcTargetEntity>(entity);
AddBuffer<NpcAttackCooldown>(entity);
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 8194ce63a01ea9044a8c5a6ebd0e2829
\ No newline at end of file
fileFormatVersion: 2
guid: 11203c5aa086c944c9075c246b46bf74
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 4e0d1427628190d4e881e3a1b16e3585
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Entities;
using Unity.Mathematics;
using Unity.NetCode;
using UnityEngine;
public struct NpcTargetRadius : IComponentData
{
public float Value;
}
public struct NpcTargetEntity : IComponentData
{
[GhostField] public Entity Value;
}
public struct NpcAttackProperties : IComponentData
{
public float3 FirePointOffset;
public uint CooldownTickCount;
public Entity AttackPrefab;
}
public struct NpcAttackCooldown : ICommandData
{
public NetworkTick Tick { get; set; }
public NetworkTick Value;
}
public struct DestroyOnTimer : IComponentData
{
public float Value;
}
public struct DestroyAtTick : IComponentData
{
[GhostField] public NetworkTick Value;
}
public struct DestroyEntityTag : IComponentData
{
}
public struct AbilityMoveSpeed : IComponentData
{
public float Value;
}
public struct DamageOnTrigger : IComponentData
{
public int Value;
}
public struct AlreadyDamagedEntity : IBufferElementData
{
public Entity Value;
}
[GhostComponent(PrefabType = GhostPrefabType.AllPredicted)]
public struct DamageBufferElement : IBufferElementData
{
public int Value;
}
[GhostComponent(PrefabType = GhostPrefabType.AllPredicted, OwnerSendType = SendToOwnerType.SendToNonOwner)]
public struct DamageThisTick : ICommandData
{
public NetworkTick Tick { get; set; }
public int Value;
}
public struct MaxHitPoints : IComponentData
{
public int Value;
}
public struct CurrentHitPoints : IComponentData
{
[GhostField] public int Value;
}
\ No newline at end of file
fileFormatVersion: 2
guid: f77d774856f11e3438214e7f45474a48
\ No newline at end of file
using Unity.Entities;
using Unity.Mathematics;
public struct CameraFollow : IComponentData
{
public Entity PlayerEntity;
public float3 Offset;
}
\ No newline at end of file
fileFormatVersion: 2
guid: 72405cbc295497045b447fc4d7fc5639
\ No newline at end of file
using Unity.Entities;
using Unity.Mathematics;
using Unity.NetCode;
using UnityEngine;
public struct NetcodePlayerInput : IInputComponentData
{
public float2 inputVector;
}
public struct PlayerSprintData : IComponentData
{
public bool isSprinting;
public bool isSprintCooldown;
public float sprintRemaining;
public float sprintDuration;
public float sprintSpeed;
public float walkSpeed;
public float sprintCooldown;
public float sprintCooldownReset;
}
public struct PlayerAttackData : IComponentData
{
public float attackCooldownTimer;
}
public struct PlayerDefenceData : IComponentData
{
public float defenceCooldownTimer;
}
public struct TeamTypes : IComponentData
{
[GhostField] public TeamType Value;
}
\ No newline at end of file
fileFormatVersion: 2
guid: 91d64865050aaad418ac0a2d66340580
\ No newline at end of file
......@@ -10,9 +10,6 @@ public class NetcodePlayerInputAuthoring : MonoBehaviour
public float sprintSpeed = 12f;
public float walkSpeed = 9f;
public float sprintCooldownReset = 2f;
public float sprintFOV = 90f;
public float walkFOV = 60f;
public float sprintFOVStepTime = 0.1f;
public class Baker : Baker<NetcodePlayerInputAuthoring>
{
......@@ -31,43 +28,10 @@ public class NetcodePlayerInputAuthoring : MonoBehaviour
walkSpeed = authoring.walkSpeed,
sprintCooldown = 0f,
sprintCooldownReset = authoring.sprintCooldownReset,
sprintFOV = authoring.sprintFOV,
walkFOV = authoring.walkFOV,
sprintFOVStepTime = authoring.sprintFOVStepTime
});
AddComponent(entity, new PlayerAttackData());
AddComponent(entity, new PlayerDefenceData());
}
}
}
public struct NetcodePlayerInput : IInputComponentData
{
public float2 inputVector;
}
public struct PlayerSprintData : IComponentData
{
public bool isSprinting;
public bool isSprintCooldown;
public float sprintRemaining;
public float sprintDuration;
public float sprintSpeed;
public float walkSpeed;
public float sprintCooldown;
public float sprintCooldownReset;
public float sprintFOV;
public float walkFOV;
public float sprintFOVStepTime;
}
public struct PlayerAttackData : IComponentData
{
public float attackCooldownTimer;
}
public struct PlayerDefenceData : IComponentData
{
public float defenceCooldownTimer;
}
\ No newline at end of file
fileFormatVersion: 2
guid: 1e447e5436fbc95409cebe1b0da18aef
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.NetCode;
using Unity.Transforms;
[UpdateInGroup(typeof(PredictedSimulationSystemGroup))]
public partial struct NpcAttackSystem : ISystem
{
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<NetworkTime>();
state.RequireForUpdate<BeginSimulationEntityCommandBufferSystem.Singleton>();
}
public void OnUpdate(ref SystemState state)
{
var ecbSingleton = SystemAPI.GetSingleton<BeginSimulationEntityCommandBufferSystem.Singleton>();
var networkTime = SystemAPI.GetSingleton<NetworkTime>();
state.Dependency = new NpcAttackJob
{
CurrentTick = networkTime.ServerTick,
TransformLookup = SystemAPI.GetComponentLookup<LocalTransform>(true),
ECB = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter()
}.ScheduleParallel(state.Dependency);
}
}
[BurstCompile]
[WithAll(typeof(Simulate))]
public partial struct NpcAttackJob : IJobEntity
{
[ReadOnly] public NetworkTick CurrentTick;
[ReadOnly] public ComponentLookup<LocalTransform> TransformLookup;
public EntityCommandBuffer.ParallelWriter ECB;
[BurstCompile]
private void Execute(ref DynamicBuffer<NpcAttackCooldown> attackCooldown, in NpcAttackProperties attackProperties,
in NpcTargetEntity targetEntity, Entity npcEntity, TeamTypes team, [ChunkIndexInQuery] int sortKey)
{
if (!TransformLookup.HasComponent(targetEntity.Value)) return;
if (!attackCooldown.GetDataAtTick(CurrentTick, out var cooldownExpirationTick))
{
cooldownExpirationTick.Value = NetworkTick.Invalid;
}
var canAttack = !cooldownExpirationTick.Value.IsValid ||
CurrentTick.IsNewerThan(cooldownExpirationTick.Value);
if (!canAttack) return;
var spawnPosition = TransformLookup[npcEntity].Position + attackProperties.FirePointOffset;
var targetPosition = TransformLookup[targetEntity.Value].Position;
var targetEntityl = targetEntity.Value;
var newAttack = ECB.Instantiate(sortKey, attackProperties.AttackPrefab);
var newAttackTransform = LocalTransform.FromPositionRotation(spawnPosition,
quaternion.LookRotationSafe(targetPosition - spawnPosition, math.up()));
ECB.SetComponent(sortKey, newAttack, newAttackTransform);
ECB.SetComponent(sortKey, newAttack, team);
var newCooldownTick = CurrentTick;
newCooldownTick.Add(attackProperties.CooldownTickCount);
attackCooldown.AddCommandData(new NpcAttackCooldown { Tick = CurrentTick, Value = newCooldownTick });
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 7d00f1c029a4ba0459a369b52aead5cd
\ No newline at end of file
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Physics;
using Unity.Physics.Systems;
using Unity.Transforms;
[UpdateInGroup(typeof(PhysicsSystemGroup))]
[UpdateAfter(typeof(PhysicsSimulationGroup))]
[UpdateBefore(typeof(ExportPhysicsWorld))]
public partial struct NpcTargetingSystem : ISystem
{
private CollisionFilter _npcAttackFilter;
[BurstCompile]
public void OnCreate(ref SystemState state)
{
state.RequireForUpdate<PhysicsWorldSingleton>();
_npcAttackFilter = new CollisionFilter
{
BelongsTo = 1 << 6, //Target Cast
CollidesWith = 1 << 1 | 1 << 4 //Player and structures
};
}
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
state.Dependency = new NpcTargetingJob
{
CollisionWorld = SystemAPI.GetSingleton<PhysicsWorldSingleton>().CollisionWorld,
CollisionFilter = _npcAttackFilter,
TeamTypeLookup = SystemAPI.GetComponentLookup<TeamTypes>(true)
}.ScheduleParallel(state.Dependency);
}
[BurstCompile]
[WithAll(typeof(Simulate))]
public partial struct NpcTargetingJob : IJobEntity
{
[ReadOnly] public CollisionWorld CollisionWorld;
[ReadOnly] public CollisionFilter CollisionFilter;
[ReadOnly] public ComponentLookup<TeamTypes> TeamTypeLookup;
[BurstCompile]
private void Execute(Entity npcEntity, ref NpcTargetEntity targetEntity, in LocalTransform transform,
in NpcTargetRadius targetRadius)
{
var hits = new NativeList<DistanceHit>(Allocator.TempJob);
if (CollisionWorld.OverlapSphere(transform.Position, targetRadius.Value, ref hits, CollisionFilter))
{
var closestDistance = float.MaxValue;
var closestEntity = Entity.Null;
foreach (var hit in hits)
{
if (!TeamTypeLookup.TryGetComponent(hit.Entity, out var mobaTeam)) continue;
if (mobaTeam.Value == TeamTypeLookup[npcEntity].Value) continue;
if (hit.Distance < closestDistance)
{
closestDistance = hit.Distance;
closestEntity = hit.Entity;
}
}
targetEntity.Value = closestEntity;
}
else
{
targetEntity.Value = Entity.Null;
}
hits.Dispose();
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 995ab538870fc4543831978f4e8a3d35
\ No newline at end of file
fileFormatVersion: 2
guid: 1ed901b8d354dfd428cfb2540ea650ae
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System;
using UnityEngine;
public enum TeamType : byte
{
None = 0,
Player = 1,
Enemy = 2,
AutoAssign = Byte.MaxValue,
}
\ No newline at end of file
fileFormatVersion: 2
guid: 981b5a55e18cda34e9c49fe0abb75202
\ No newline at end of file
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &357967689053387235
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 874719443322819787}
- component: {fileID: 4261204768695203471}
- component: {fileID: 1760952723452715749}
- component: {fileID: 2779256602276023860}
- component: {fileID: 1149029900162062154}
- component: {fileID: 1366604838159312984}
- component: {fileID: 637409898788639419}
- component: {fileID: 3098296856090571708}
- component: {fileID: 8588236733928965914}
m_Layer: 0
m_Name: Arrow
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &874719443322819787
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7132425822489606939}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4261204768695203471
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b275e5f92732148048d7b77e264ac30e, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ShapeType: 0
m_PrimitiveCenter:
x: -0.000003438443
y: -0.016935043
z: -0.008655369
m_PrimitiveSize:
x: 0.117339954
y: 0.10162632
z: 0.7485465
m_PrimitiveOrientation:
Value:
x: -0
y: 0
z: 0
RotationOrder: 4
m_Capsule:
Height: 0.7485465
Radius: 0.058669977
Axis: 2
m_Cylinder:
Height: 0.7485465
Radius: 0.058669977
Axis: 2
m_CylinderSideCount: 20
m_SphereRadius: 0.37427324
m_MinimumSkinnedVertexWeight: 0.1
m_ConvexHullGenerationParameters:
m_SimplificationTolerance: 0.011228197
m_BevelRadius: 0.05
m_MinimumAngle: 2.5000002
m_CustomMesh: {fileID: 0}
m_ForceUnique: 0
m_Material:
m_SupportsTemplate: 1
m_Template: {fileID: 0}
m_CollisionResponse:
m_Override: 0
m_Value: 3
m_Friction:
m_Override: 0
m_Value:
Value: 0.5
CombineMode: 0
m_Restitution:
m_Override: 0
m_Value:
Value: 0
CombineMode: 2
m_BelongsToCategories:
m_Override: 0
m_Value:
Category00: 0
Category01: 0
Category02: 0
Category03: 1
Category04: 0
Category05: 0
Category06: 0
Category07: 0
Category08: 0
Category09: 0
Category10: 0
Category11: 0
Category12: 0
Category13: 0
Category14: 0
Category15: 0
Category16: 0
Category17: 0
Category18: 0
Category19: 0
Category20: 0
Category21: 0
Category22: 0
Category23: 0
Category24: 0
Category25: 0
Category26: 0
Category27: 0
Category28: 0
Category29: 0
Category30: 0
Category31: 0
m_CollidesWithCategories:
m_Override: 0
m_Value:
Category00: 0
Category01: 1
Category02: 0
Category03: 0
Category04: 1
Category05: 0
Category06: 0
Category07: 0
Category08: 0
Category09: 0
Category10: 0
Category11: 0
Category12: 0
Category13: 0
Category14: 0
Category15: 0
Category16: 0
Category17: 0
Category18: 0
Category19: 0
Category20: 0
Category21: 0
Category22: 0
Category23: 0
Category24: 0
Category25: 0
Category26: 0
Category27: 0
Category28: 0
Category29: 0
Category30: 0
Category31: 0
m_CustomMaterialTags:
m_Override: 0
m_Value:
Tag00: 0
Tag01: 0
Tag02: 0
Tag03: 0
Tag04: 0
Tag05: 0
Tag06: 0
Tag07: 0
m_SerializedVersion: 1
m_SerializedVersion: 1
--- !u!54 &1760952723452715749
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
serializedVersion: 4
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_CenterOfMass: {x: 0, y: 0, z: 0}
m_InertiaTensor: {x: 1, y: 1, z: 1}
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_ImplicitCom: 1
m_ImplicitTensor: 1
m_UseGravity: 0
m_IsKinematic: 1
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!114 &2779256602276023860
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7e19d579a4586dd40805276eb2d1a684, type: 3}
m_Name:
m_EditorClassIdentifier:
DestroyOnTimer: 2
--- !u!114 &1149029900162062154
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1f03a841418196747bbd25842c79de4f, type: 3}
m_Name:
m_EditorClassIdentifier:
AbilityMoveSpeed: 10
--- !u!114 &1366604838159312984
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &637409898788639419
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8b4cd120b33db8143be607a7d5012817, type: 3}
m_Name:
m_EditorClassIdentifier:
TeamType: 2
--- !u!114 &3098296856090571708
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
m_Name:
m_EditorClassIdentifier:
DefaultGhostMode: 1
SupportedGhostModes: 3
OptimizationMode: 0
Importance: 500
MaxSendRate: 0
prefabId: 19127a4c1ac11844db4373b9e147918b
HasOwner: 0
SupportAutoCommandTarget: 1
TrackInterpolationDelay: 0
GhostGroup: 0
UsePreSerialization: 0
RollbackPredictedSpawnedGhostState: 0
RollbackPredictionOnStructuralChanges: 1
--- !u!114 &8588236733928965914
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 357967689053387235}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2de495c310a322143be08aa7819a1a33, type: 3}
m_Name:
m_EditorClassIdentifier:
DamageOnTrigger: 100
--- !u!1001 &7309850180045348080
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 874719443322819787}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalPosition.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
propertyPath: m_Name
value: Skeleton_Arrow
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
--- !u!4 &7132425822489606939 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 383b8acbdeeb36f45805802bf80f9774, type: 3}
m_PrefabInstance: {fileID: 7309850180045348080}
m_PrefabAsset: {fileID: 0}
fileFormatVersion: 2
guid: 19127a4c1ac11844db4373b9e147918b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4119712591281040369
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4518211183990774724}
- component: {fileID: 2582803764958419624}
- component: {fileID: 544445575287296422}
- component: {fileID: 1795119605167857545}
- component: {fileID: 7671856692459541817}
- component: {fileID: 7330549200574829686}
- component: {fileID: 3643359558555697495}
m_Layer: 0
m_Name: RogueEnemy
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4518211183990774724
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 79546426197936465}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2582803764958419624
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c16549610bfe4458aa9389201d072bb6, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &544445575287296422
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8b4cd120b33db8143be607a7d5012817, type: 3}
m_Name:
m_EditorClassIdentifier:
TeamType: 2
--- !u!114 &1795119605167857545
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c79d771cedb4794bf100ce60df5f764, type: 3}
m_Name:
m_EditorClassIdentifier:
DefaultGhostMode: 0
SupportedGhostModes: 3
OptimizationMode: 0
Importance: 1
MaxSendRate: 0
prefabId: 31ddab13d76d526499c2002833a10312
HasOwner: 0
SupportAutoCommandTarget: 1
TrackInterpolationDelay: 0
GhostGroup: 0
UsePreSerialization: 0
RollbackPredictedSpawnedGhostState: 0
RollbackPredictionOnStructuralChanges: 1
--- !u!114 &7671856692459541817
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8194ce63a01ea9044a8c5a6ebd0e2829, type: 3}
m_Name:
m_EditorClassIdentifier:
NpcTargetRadius: 15
AttackCooldownTime: 0
FirePointOffset: {x: 0, y: 2.5, z: 0}
AttackPrefab: {fileID: 357967689053387235, guid: 19127a4c1ac11844db4373b9e147918b, type: 3}
NetCodeConfig: {fileID: 11400000, guid: cd69de227738309429193c9089949c16, type: 2}
--- !u!114 &7330549200574829686
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b275e5f92732148048d7b77e264ac30e, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ShapeType: 3
m_PrimitiveCenter:
x: 0
y: 1
z: 0
m_PrimitiveSize:
x: 1.52
y: 1.52
z: 2.307949
m_PrimitiveOrientation:
Value:
x: -90
y: 0
z: -90
RotationOrder: 4
m_Capsule:
Height: 2.307949
Radius: 0.76
Axis: 2
m_Cylinder:
Height: 2.307949
Radius: 0.76
Axis: 2
m_CylinderSideCount: 8
m_SphereRadius: 1.1539745
m_MinimumSkinnedVertexWeight: 0.1
m_ConvexHullGenerationParameters:
m_SimplificationTolerance: 0.03461923
m_BevelRadius: 0.05
m_MinimumAngle: 2.5000002
m_CustomMesh: {fileID: 0}
m_ForceUnique: 0
m_Material:
m_SupportsTemplate: 1
m_Template: {fileID: 0}
m_CollisionResponse:
m_Override: 0
m_Value: 0
m_Friction:
m_Override: 0
m_Value:
Value: 0.5
CombineMode: 0
m_Restitution:
m_Override: 0
m_Value:
Value: 0
CombineMode: 2
m_BelongsToCategories:
m_Override: 0
m_Value:
Category00: 0
Category01: 0
Category02: 1
Category03: 0
Category04: 0
Category05: 0
Category06: 0
Category07: 0
Category08: 0
Category09: 0
Category10: 0
Category11: 0
Category12: 0
Category13: 0
Category14: 0
Category15: 0
Category16: 0
Category17: 0
Category18: 0
Category19: 0
Category20: 0
Category21: 0
Category22: 0
Category23: 0
Category24: 0
Category25: 0
Category26: 0
Category27: 0
Category28: 0
Category29: 0
Category30: 0
Category31: 0
m_CollidesWithCategories:
m_Override: 0
m_Value:
Category00: 1
Category01: 1
Category02: 0
Category03: 1
Category04: 0
Category05: 0
Category06: 0
Category07: 0
Category08: 0
Category09: 0
Category10: 0
Category11: 0
Category12: 0
Category13: 0
Category14: 0
Category15: 0
Category16: 0
Category17: 0
Category18: 0
Category19: 0
Category20: 0
Category21: 0
Category22: 0
Category23: 0
Category24: 0
Category25: 0
Category26: 0
Category27: 0
Category28: 0
Category29: 0
Category30: 0
Category31: 0
m_CustomMaterialTags:
m_Override: 0
m_Value:
Tag00: 0
Tag01: 0
Tag02: 0
Tag03: 0
Tag04: 0
Tag05: 0
Tag06: 0
Tag07: 0
m_SerializedVersion: 1
m_SerializedVersion: 1
--- !u!54 &3643359558555697495
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4119712591281040369}
serializedVersion: 4
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_CenterOfMass: {x: 0, y: 0, z: 0}
m_InertiaTensor: {x: 1, y: 1, z: 1}
m_InertiaRotation: {x: 0, y: 0, z: 0, w: 1}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_ImplicitCom: 1
m_ImplicitTensor: 1
m_UseGravity: 0
m_IsKinematic: 1
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!1 &8774680188425444558
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 79546426197936465}
m_Layer: 0
m_Name: EnemyVisual
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &79546426197936465
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8774680188425444558}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1170849029280685222}
m_Father: {fileID: 4518211183990774724}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &1708282080718207821
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 79546426197936465}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
propertyPath: m_Name
value: Skeleton_Rogue
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
--- !u!4 &1170849029280685222 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 157b48a66b6c1ca41943a6a9a3892ecf, type: 3}
m_PrefabInstance: {fileID: 1708282080718207821}
m_PrefabAsset: {fileID: 0}
fileFormatVersion: 2
guid: 31ddab13d76d526499c2002833a10312
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -25,7 +25,7 @@ Transform:
m_GameObject: {fileID: 650624935253927002}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: -0.77, z: 0}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1.81, y: 1.81, z: 1.81}
m_ConstrainProportionsScale: 1
m_Children:
......@@ -57,7 +57,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 728568152667097525}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
......@@ -98,8 +98,7 @@ Transform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5718679709133256066}
m_Children: []
m_Father: {fileID: 3251327355353088423}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &5250389714568146909
......@@ -130,8 +129,7 @@ Transform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4769926944719908952}
m_Children: []
m_Father: {fileID: 3251327355353088423}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &5510887720992502651
......@@ -162,9 +160,7 @@ Transform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5631455044536526149}
- {fileID: 6214961402451407269}
m_Children: []
m_Father: {fileID: 3251327355353088423}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &7261106503907252533
......@@ -252,8 +248,7 @@ Transform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7834305409683949638}
m_Children: []
m_Father: {fileID: 3251327355353088423}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &7584320928867012029
......@@ -284,92 +279,9 @@ Transform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 5798277484775124278}
m_Children: []
m_Father: {fileID: 3251327355353088423}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &565620134248262404
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 5981432708657565925}
m_Modifications:
- target: {fileID: 163114042722539874, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: GlobalObjectIdHash
value: 1837939063
objectReference: {fileID: 0}
- target: {fileID: 163114042722539874, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: InScenePlacedSourceGlobalObjectIdHash
value: 1023450164
objectReference: {fileID: 0}
- target: {fileID: 2142678194451976319, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_Name
value: ExplosiveB
objectReference: {fileID: 0}
- target: {fileID: 2810168411361310003, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_Center.y
value: -0.16
objectReference: {fileID: 0}
- target: {fileID: 5365762707953752018, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalPosition.y
value: -0.6
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalPosition.x
value: 0.16
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalPosition.z
value: -5.62
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8877540788060270672, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
propertyPath: followTransformSettings
value:
objectReference: {fileID: 11400000, guid: 28235d84f1cad684594e8fce9f404b5d, type: 2}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
--- !u!4 &7834305409683949638 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7737315830459736898, guid: 835d789898f8f3a4d97189425e75e8f6, type: 3}
m_PrefabInstance: {fileID: 565620134248262404}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &706217386485487288
PrefabInstance:
m_ObjectHideFlags: 0
......@@ -1490,72 +1402,6 @@ MeshCollider:
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 4476593937870996573, guid: 87d9e8aa89dc79e47bbc07b25704225c, type: 3}
--- !u!1001 &3334370746320987030
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 2438670058733636552}
m_Modifications:
- target: {fileID: 1580681325717503087, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: GlobalObjectIdHash
value: 364363177
objectReference: {fileID: 0}
- target: {fileID: 4727207244663773237, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_Name
value: Barrel
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalPosition.x
value: 5.24
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalPosition.y
value: -0.74
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalPosition.z
value: -12.18
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 525df842114a50742b87e2282140ad02, type: 3}
--- !u!4 &6214961402451407269 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
m_PrefabInstance: {fileID: 3334370746320987030}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &3645143903690725698
PrefabInstance:
m_ObjectHideFlags: 0
......@@ -1648,72 +1494,6 @@ MeshCollider:
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 4040528778396390922, guid: 2abc46d65f2e2d7439c7689b3c2142c4, type: 3}
--- !u!1001 &3917877096661514102
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 2438670058733636552}
m_Modifications:
- target: {fileID: 1580681325717503087, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: GlobalObjectIdHash
value: 2089084133
objectReference: {fileID: 0}
- target: {fileID: 4727207244663773237, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_Name
value: Barrel
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalPosition.x
value: -1.33
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalPosition.y
value: -0.74
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalPosition.z
value: -11.58
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 525df842114a50742b87e2282140ad02, type: 3}
--- !u!4 &5631455044536526149 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 8681228075763733043, guid: 525df842114a50742b87e2282140ad02, type: 3}
m_PrefabInstance: {fileID: 3917877096661514102}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &4695005921061930150
PrefabInstance:
m_ObjectHideFlags: 0
......@@ -1806,176 +1586,6 @@ MeshCollider:
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 4040528778396390922, guid: 2abc46d65f2e2d7439c7689b3c2142c4, type: 3}
--- !u!1001 &5023930542033557427
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 5001222007940412494}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalPosition.x
value: 9.31
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalPosition.y
value: -0.7321186
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalPosition.z
value: -4.676365
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalRotation.x
value: 0.00000008146034
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_Name
value: wall_doorway
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
propertyPath: m_Layer
value: 6
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
insertIndex: -1
addedObject: {fileID: 1797716311453716103}
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
insertIndex: -1
addedObject: {fileID: 725737077070417987}
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
insertIndex: -1
addedObject: {fileID: 5281452119083837664}
- targetCorrespondingSourceObject: {fileID: 3245047377962470163, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
insertIndex: -1
addedObject: {fileID: 2529430209839376466}
m_SourcePrefab: {fileID: 100100000, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
--- !u!4 &4769926944719908952 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
m_PrefabInstance: {fileID: 5023930542033557427}
m_PrefabAsset: {fileID: 0}
--- !u!1 &5294544192241429218 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
m_PrefabInstance: {fileID: 5023930542033557427}
m_PrefabAsset: {fileID: 0}
--- !u!64 &1797716311453716103
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5294544192241429218}
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: 5
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 4196161430825003242, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
--- !u!114 &725737077070417987
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5294544192241429218}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8b1dab2eab11c8a47a37ae0eadf44baa, type: 3}
m_Name:
m_EditorClassIdentifier:
ShowTopMostFoldoutHeaderGroup: 1
--- !u!114 &5281452119083837664
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5294544192241429218}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d5a57f767e5e46a458fc5d3c628d0cbb, type: 3}
m_Name:
m_EditorClassIdentifier:
GlobalObjectIdHash: 657873038
InScenePlacedSourceGlobalObjectIdHash: 0
DeferredDespawnTick: 0
Ownership: 1
AlwaysReplicateAsRoot: 0
SynchronizeTransform: 1
ActiveSceneSynchronization: 0
SceneMigrationSynchronization: 1
SpawnWithObservers: 1
DontDestroyWithOwner: 0
AutoObjectParentSync: 1
SyncOwnerTransformWhenParented: 1
AllowOwnerToParent: 0
--- !u!1 &7543581398450396320 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 3245047377962470163, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
m_PrefabInstance: {fileID: 5023930542033557427}
m_PrefabAsset: {fileID: 0}
--- !u!64 &2529430209839376466
MeshCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7543581398450396320}
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: 5
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 7430001191524928491, guid: 6cdf95d64713790459b9ebea4dd28535, type: 3}
--- !u!1001 &5217666724057532685
PrefabInstance:
m_ObjectHideFlags: 0
......@@ -2344,142 +1954,6 @@ MeshCollider:
m_Convex: 0
m_CookingOptions: 30
m_Mesh: {fileID: 4476593937870996573, guid: 87d9e8aa89dc79e47bbc07b25704225c, type: 3}
--- !u!1001 &6303547948751003510
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 1806774946114198236}
m_Modifications:
- target: {fileID: 334567762338569054, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_Name
value: Chest
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalPosition.x
value: -3
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalPosition.y
value: -0.74
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalPosition.z
value: -1.19
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalRotation.w
value: 0
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalRotation.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 180
objectReference: {fileID: 0}
- target: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3719657908984160168, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
propertyPath: GlobalObjectIdHash
value: 41515216
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
--- !u!4 &5798277484775124278 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 508112708245697088, guid: dc502d59cef13ed40b07aa18bd1a4167, type: 3}
m_PrefabInstance: {fileID: 6303547948751003510}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &6375309094765546322
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 5581542974833947271}
m_Modifications:
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalPosition.x
value: -2.182
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalPosition.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalPosition.z
value: 5.667
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalRotation.x
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 90
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3668773499323874180, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: GlobalObjectIdHash
value: 2868596387
objectReference: {fileID: 0}
- target: {fileID: 8050255731901760503, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: m_Name
value: Key
objectReference: {fileID: 0}
- target: {fileID: 9087763765203173466, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
propertyPath: followTransformSettings
value:
objectReference: {fileID: 11400000, guid: 5f3f18b211ea1704fbb884929d9cf33d, type: 2}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
--- !u!4 &5718679709133256066 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 1667863745995374288, guid: 1d9ae894a89fd38449f1ce889f52d1ad, type: 3}
m_PrefabInstance: {fileID: 6375309094765546322}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &6660476097823711337
PrefabInstance:
m_ObjectHideFlags: 0
......
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1001200712104652852
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4400096938535222231}
- component: {fileID: 8986874467296708868}
m_Layer: 5
m_Name: HealthBarSlider
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4400096938535222231
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1001200712104652852}
m_LocalRotation: {x: 0.5, y: 0, z: 0, w: 0.8660254}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7256984764435283722}
- {fileID: 885732674323091756}
- {fileID: 1049164032731023949}
- {fileID: 6194065087393849582}
m_Father: {fileID: 8603131648779679062}
m_LocalEulerAnglesHint: {x: 60, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 200, y: 75}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &8986874467296708868
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1001200712104652852}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 0}
m_FillRect: {fileID: 3347823832458425704}
m_HandleRect: {fileID: 0}
m_Direction: 0
m_MinValue: 0
m_MaxValue: 1000
m_WholeNumbers: 1
m_Value: 750
m_OnValueChanged:
m_PersistentCalls:
m_Calls: []
--- !u!1 &1717650747662098735
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7256984764435283722}
- component: {fileID: 1546765485606351003}
- component: {fileID: 6012739619884274136}
m_Layer: 5
m_Name: Outline
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7256984764435283722
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1717650747662098735}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4400096938535222231}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 10, y: 10}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1546765485606351003
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1717650747662098735}
m_CullTransparentMesh: 1
--- !u!114 &6012739619884274136
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1717650747662098735}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &1976058127480658131
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1049164032731023949}
m_Layer: 5
m_Name: Fill Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1049164032731023949
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1976058127480658131}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3347823832458425704}
m_Father: {fileID: 4400096938535222231}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &6246730936639062891
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8603131648779679062}
- component: {fileID: 7587403821176963594}
- component: {fileID: 915452237788923504}
- component: {fileID: 8484270301105423308}
m_Layer: 5
m_Name: HealthBarCanvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8603131648779679062
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246730936639062891}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.01, y: 0.01, z: 0.01}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 4400096938535222231}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 3}
m_SizeDelta: {x: 1000, y: 1000}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!223 &7587403821176963594
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246730936639062891}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 2
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 1
m_AdditionalShaderChannelsFlag: 0
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!114 &915452237788923504
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246730936639062891}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 1
--- !u!114 &8484270301105423308
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246730936639062891}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!1 &8316567548703684641
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3347823832458425704}
- component: {fileID: 6962439563796182759}
- component: {fileID: 767712265345608757}
m_Layer: 5
m_Name: Fill
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3347823832458425704
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8316567548703684641}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1049164032731023949}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6962439563796182759
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8316567548703684641}
m_CullTransparentMesh: 1
--- !u!114 &767712265345608757
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8316567548703684641}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.32768464, g: 0.9622642, b: 0.28595585, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &9065435171117998417
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6194065087393849582}
m_Layer: 5
m_Name: Handle Slide Area
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6194065087393849582
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9065435171117998417}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4400096938535222231}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &9114559658134269579
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 885732674323091756}
- component: {fileID: 4560447777914159299}
- component: {fileID: 2437271104078609728}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &885732674323091756
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9114559658134269579}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 4400096938535222231}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.25}
m_AnchorMax: {x: 1, y: 0.75}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4560447777914159299
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9114559658134269579}
m_CullTransparentMesh: 1
--- !u!114 &2437271104078609728
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9114559658134269579}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.5566038, g: 0, b: 0, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
fileFormatVersion: 2
guid: 8aadaf8ffd0c86343a26b96a6d7bb1fd
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -45,8 +45,8 @@ GameObject:
- component: {fileID: 4231599962978745826}
- component: {fileID: 4041478062616122735}
- component: {fileID: 2660614573323502624}
- component: {fileID: 3088076614356089153}
- component: {fileID: 4693948394273888574}
- component: {fileID: 3955402020692204287}
- component: {fileID: 1305669273409567159}
m_Layer: 0
m_Name: Player
m_TagString: Untagged
......@@ -151,10 +151,7 @@ MonoBehaviour:
sprintSpeed: 12
walkSpeed: 9
sprintCooldownReset: 2
sprintFOV: 90
walkFOV: 60
sprintFOVStepTime: 0.1
--- !u!114 &3088076614356089153
--- !u!114 &3955402020692204287
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
......@@ -163,34 +160,153 @@ MonoBehaviour:
m_GameObject: {fileID: 5874026590232167095}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 725f443b46fd3448e9c957fb78798883, type: 3}
m_Script: {fileID: 11500000, guid: 8b4cd120b33db8143be607a7d5012817, type: 3}
m_Name:
m_EditorClassIdentifier:
ServerPrefab: {fileID: 0}
ClientPrefab: {fileID: 2376445730206303677, guid: 4e5cb8aa1739e0e4e9f39ec61f344ee2, type: 3}
--- !u!136 &4693948394273888574
CapsuleCollider:
TeamType: 1
--- !u!114 &1305669273409567159
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5874026590232167095}
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: 2
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 1, z: 0}
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b275e5f92732148048d7b77e264ac30e, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ShapeType: 3
m_PrimitiveCenter:
x: 0
y: 1.0830303
z: -0.0023028553
m_PrimitiveSize:
x: 1.24
y: 1.24
z: 2.1661136
m_PrimitiveOrientation:
Value:
x: 90
y: 0
z: 0
RotationOrder: 4
m_Capsule:
Height: 2.1661136
Radius: 0.62
Axis: 2
m_Cylinder:
Height: 2.1661136
Radius: 0.62
Axis: 2
m_CylinderSideCount: 8
m_SphereRadius: 1.0830568
m_MinimumSkinnedVertexWeight: 0.1
m_ConvexHullGenerationParameters:
m_SimplificationTolerance: 0.032491703
m_BevelRadius: 0.05
m_MinimumAngle: 2.5000002
m_CustomMesh: {fileID: 0}
m_ForceUnique: 0
m_Material:
m_SupportsTemplate: 1
m_Template: {fileID: 0}
m_CollisionResponse:
m_Override: 0
m_Value: 0
m_Friction:
m_Override: 0
m_Value:
Value: 0.5
CombineMode: 0
m_Restitution:
m_Override: 0
m_Value:
Value: 0
CombineMode: 2
m_BelongsToCategories:
m_Override: 0
m_Value:
Category00: 0
Category01: 1
Category02: 0
Category03: 0
Category04: 0
Category05: 0
Category06: 0
Category07: 0
Category08: 0
Category09: 0
Category10: 0
Category11: 0
Category12: 0
Category13: 0
Category14: 0
Category15: 0
Category16: 0
Category17: 0
Category18: 0
Category19: 0
Category20: 0
Category21: 0
Category22: 0
Category23: 0
Category24: 0
Category25: 0
Category26: 0
Category27: 0
Category28: 0
Category29: 0
Category30: 0
Category31: 0
m_CollidesWithCategories:
m_Override: 0
m_Value:
Category00: 1
Category01: 1
Category02: 1
Category03: 1
Category04: 1
Category05: 1
Category06: 1
Category07: 1
Category08: 1
Category09: 1
Category10: 1
Category11: 1
Category12: 1
Category13: 1
Category14: 1
Category15: 1
Category16: 1
Category17: 1
Category18: 1
Category19: 1
Category20: 1
Category21: 1
Category22: 1
Category23: 1
Category24: 1
Category25: 1
Category26: 1
Category27: 1
Category28: 1
Category29: 1
Category30: 1
Category31: 1
m_CustomMaterialTags:
m_Override: 0
m_Value:
Tag00: 0
Tag01: 0
Tag02: 0
Tag03: 0
Tag04: 0
Tag05: 0
Tag06: 0
Tag07: 0
m_SerializedVersion: 1
m_SerializedVersion: 1
--- !u!1001 &6975352639711469968
PrefabInstance:
m_ObjectHideFlags: 0
......
......@@ -131,10 +131,6 @@ PrefabInstance:
propertyPath: m_Name
value: Environment
objectReference: {fileID: 0}
- target: {fileID: 728568152667097525, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3251327355353088423, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_LocalPosition.x
value: 0
......@@ -175,18 +171,8 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7261106503907252533, guid: 2533a95934a9ea044a5454189730090b, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects:
- {fileID: 5294544192241429218, guid: 2533a95934a9ea044a5454189730090b, type: 3}
- {fileID: -5589040876848833456, guid: 2533a95934a9ea044a5454189730090b, type: 3}
- {fileID: -2900474049171270216, guid: 2533a95934a9ea044a5454189730090b, type: 3}
- {fileID: 5154027267669139303, guid: 2533a95934a9ea044a5454189730090b, type: 3}
- {fileID: 5272548991785216674, guid: 2533a95934a9ea044a5454189730090b, type: 3}
- {fileID: 119866018441783341, guid: 2533a95934a9ea044a5454189730090b, type: 3}
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2533a95934a9ea044a5454189730090b, type: 3}
......@@ -235,9 +221,67 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
playerPrefabGameObject: {fileID: 5874026590232167095, guid: 7ea025f0d02f62a4b8c0db52b410e781, type: 3}
--- !u!1001 &1719764137
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 4119712591281040369, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_Name
value: RogueEnemy
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalPosition.x
value: -18.12
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4518211183990774724, guid: 31ddab13d76d526499c2002833a10312, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 31ddab13d76d526499c2002833a10312, type: 3}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 285643545}
- {fileID: 1434796876}
- {fileID: 1719764137}
......@@ -830,7 +830,7 @@ PlayerSettings:
PS5: DOTWEEN
QNX: DOTWEEN
ReservedCFE: DOTWEEN
Standalone: DOTWEEN
Standalone: DOTWEEN;UNITY_PHYSICS_CUSTOM
VisionOS: DOTWEEN
WebGL: DOTWEEN
Windows Store Apps: DOTWEEN
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment