修改水
This commit is contained in:
70
Assets/Obi/Scripts/Common/Updaters/ObiFixedUpdater.cs
Normal file
70
Assets/Obi/Scripts/Common/Updaters/ObiFixedUpdater.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
/// <summary>
|
||||
/// Updater class that will perform simulation during FixedUpdate(). This is the most physically correct updater,
|
||||
/// and the one to be used in most cases. Also allows to perform substepping, greatly improving convergence.
|
||||
|
||||
[AddComponentMenu("Physics/Obi/Obi Fixed Updater", 801)]
|
||||
[ExecuteInEditMode]
|
||||
public class ObiFixedUpdater : ObiUpdater
|
||||
{
|
||||
/// <summary>
|
||||
/// Each FixedUpdate() call will be divided into several substeps. Performing more substeps will greatly improve the accuracy/convergence speed of the simulation.
|
||||
/// Increasing the amount of substeps is more effective than increasing the amount of constraint iterations.
|
||||
/// </summary>
|
||||
[Tooltip("Amount of substeps performed per FixedUpdate. Increasing the amount of substeps greatly improves accuracy and convergence speed.")]
|
||||
public int substeps = 4;
|
||||
|
||||
[NonSerialized] private float accumulatedTime;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
substeps = Mathf.Max(1, substeps);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
accumulatedTime = 0;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Physics.autoSimulation = true;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
ObiProfiler.EnableProfiler();
|
||||
|
||||
PrepareFrame();
|
||||
|
||||
BeginStep(Time.fixedDeltaTime);
|
||||
|
||||
float substepDelta = Time.fixedDeltaTime / (float)substeps;
|
||||
|
||||
// Divide the step into multiple smaller substeps:
|
||||
for (int i = 0; i < substeps; ++i)
|
||||
Substep(Time.fixedDeltaTime, substepDelta, substeps-i);
|
||||
|
||||
EndStep(substepDelta);
|
||||
|
||||
ObiProfiler.DisableProfiler();
|
||||
|
||||
accumulatedTime -= Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
accumulatedTime += Time.deltaTime;
|
||||
|
||||
ObiProfiler.EnableProfiler();
|
||||
Interpolate(Time.fixedDeltaTime, accumulatedTime);
|
||||
ObiProfiler.DisableProfiler();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/Updaters/ObiFixedUpdater.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/Updaters/ObiFixedUpdater.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d9704d540ac448439a425526f6b2986
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 4e2c952f509ae40bdaf836136058d487, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
84
Assets/Obi/Scripts/Common/Updaters/ObiLateFixedUpdater.cs
Normal file
84
Assets/Obi/Scripts/Common/Updaters/ObiLateFixedUpdater.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
/// <summary>
|
||||
/// Updater class that will perform simulation after WaitForFixedUpdate. Use this for simulations that require animation data as input, such as character clothing.
|
||||
/// Make sure to set the Animator update mode to "Animate Physics".
|
||||
|
||||
[AddComponentMenu("Physics/Obi/Obi Late Fixed Updater", 802)]
|
||||
[ExecuteInEditMode]
|
||||
public class ObiLateFixedUpdater : ObiUpdater
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Each LateFixedUpdate() call will be divided into several substeps. Performing more substeps will greatly improve the accuracy/convergence speed of the simulation.
|
||||
/// Increasing the amount of substeps is more effective than increasing the amount of constraint iterations.
|
||||
/// </summary>
|
||||
[Tooltip("Amount of substeps performed per FixedUpdate. Increasing the amount of substeps greatly improves accuracy and convergence speed.")]
|
||||
public int substeps = 4;
|
||||
|
||||
[NonSerialized] private float accumulatedTime;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
substeps = Mathf.Max(1, substeps);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
accumulatedTime = 0;
|
||||
StartCoroutine(RunLateFixedUpdate());
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
StopCoroutine(RunLateFixedUpdate());
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
PrepareFrame();
|
||||
}
|
||||
|
||||
private IEnumerator RunLateFixedUpdate()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
yield return new WaitForFixedUpdate();
|
||||
if (Application.isPlaying)
|
||||
LateFixedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void LateFixedUpdate()
|
||||
{
|
||||
ObiProfiler.EnableProfiler();
|
||||
|
||||
BeginStep(Time.fixedDeltaTime);
|
||||
|
||||
float substepDelta = Time.fixedDeltaTime / (float)substeps;
|
||||
|
||||
// Divide the step into multiple smaller substeps:
|
||||
for (int i = 0; i < substeps; ++i)
|
||||
Substep(Time.fixedDeltaTime, substepDelta, substeps - i);
|
||||
|
||||
EndStep(substepDelta);
|
||||
|
||||
ObiProfiler.DisableProfiler();
|
||||
|
||||
accumulatedTime -= Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
accumulatedTime += Time.deltaTime;
|
||||
|
||||
ObiProfiler.EnableProfiler();
|
||||
Interpolate(Time.fixedDeltaTime, accumulatedTime);
|
||||
ObiProfiler.DisableProfiler();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 434ec3c1822e84ae79a7f64f950b1bf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 4e2c952f509ae40bdaf836136058d487, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
72
Assets/Obi/Scripts/Common/Updaters/ObiLateUpdater.cs
Normal file
72
Assets/Obi/Scripts/Common/Updaters/ObiLateUpdater.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
/// <summary>
|
||||
/// Updater class that will perform simulation during LateUpdate(). This is highly unphysical and should be avoided whenever possible.
|
||||
/// This updater does not make any accuracy guarantees when it comes to two-way coupling with rigidbodies.
|
||||
/// It is only provided for the odd case when there's no way to perform simulation with a fixed timestep.
|
||||
/// If in doubt, use the ObiFixedUpdater component instead.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Physics/Obi/Obi Late Updater", 802)]
|
||||
public class ObiLateUpdater : ObiUpdater
|
||||
{
|
||||
/// <summary>
|
||||
/// Smoothing factor fo the timestep (smoothDelta). Values closer to 1 will yield stabler simulation, but it will be off-sync with rendering.
|
||||
/// </summary>
|
||||
[Tooltip("Smoothing factor fo the timestep (smoothDelta). Values closer to 1 will yield stabler simulation, but it will be off-sync with rendering.")]
|
||||
[Range(0,1)]
|
||||
public float deltaSmoothing = 0.95f;
|
||||
|
||||
/// <summary>
|
||||
/// Target timestep used to advance the simulation. The updater will interpolate this value with Time.deltaTime to find the actual timestep used for each frame.
|
||||
/// </summary>
|
||||
[Tooltip("Target timestep used to advance the simulation. The updater will interpolate this value with Time.deltaTime to find the actual timestep used for each frame.")]
|
||||
private float smoothDelta = 0.02f;
|
||||
|
||||
/// <summary>
|
||||
/// Each FixedUpdate() call will be divided into several substeps. Performing more substeps will greatly improve the accuracy/convergence speed of the simulation.
|
||||
/// Increasing the amount of substeps is more effective than increasing the amount of constraint iterations.
|
||||
/// </summary>
|
||||
[Tooltip("Amount of substeps performed per FixedUpdate. Increasing the amount of substeps greatly improves accuracy and convergence speed.")]
|
||||
public int substeps = 4;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
smoothDelta = Mathf.Max(0.0001f, smoothDelta);
|
||||
substeps = Mathf.Max(1, substeps);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
PrepareFrame();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Time.deltaTime > 0)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
// smooth out timestep:
|
||||
smoothDelta = Mathf.Lerp(Time.deltaTime, smoothDelta, deltaSmoothing);
|
||||
|
||||
BeginStep(smoothDelta);
|
||||
|
||||
float substepDelta = smoothDelta / (float)substeps;
|
||||
|
||||
// Divide the step into multiple smaller substeps:
|
||||
for (int i = 0; i < substeps; ++i)
|
||||
Substep(smoothDelta, substepDelta, substeps - i);
|
||||
|
||||
EndStep(substepDelta);
|
||||
}
|
||||
|
||||
Interpolate(smoothDelta, smoothDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/Updaters/ObiLateUpdater.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/Updaters/ObiLateUpdater.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 434d88f9b3534406382ff56c0e74bd9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 4e2c952f509ae40bdaf836136058d487, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
136
Assets/Obi/Scripts/Common/Updaters/ObiUpdater.cs
Normal file
136
Assets/Obi/Scripts/Common/Updaters/ObiUpdater.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using UnityEngine;
|
||||
using Unity.Profiling;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
using Unity.Jobs;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for updating multiple solvers in parallel.
|
||||
/// Derive from this class to write your onw updater. This grants you precise control over execution order,
|
||||
/// as you can choose to update solvers at any point during Unity's update cycle.
|
||||
/// </summary>
|
||||
[ExecuteInEditMode]
|
||||
public abstract class ObiUpdater : MonoBehaviour
|
||||
{
|
||||
static ProfilerMarker m_BeginStepPerfMarker = new ProfilerMarker("BeginStep");
|
||||
static ProfilerMarker m_SubstepPerfMarker = new ProfilerMarker("Substep");
|
||||
static ProfilerMarker m_EndStepPerfMarker = new ProfilerMarker("EndStep");
|
||||
static ProfilerMarker m_InterpolatePerfMarker = new ProfilerMarker("Interpolate");
|
||||
|
||||
/// <summary>
|
||||
/// List of solvers updated by this updater.
|
||||
/// </summary>
|
||||
public List<ObiSolver> solvers = new List<ObiSolver>();
|
||||
|
||||
private List<IObiJobHandle> handles = new List<IObiJobHandle>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Prepares all solvers to begin simulating a new frame. This should be called as soon as possible in the frame,
|
||||
/// and guaranteed to be called every frame that will step physics.
|
||||
/// </summary>
|
||||
protected void PrepareFrame()
|
||||
{
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
solver.PrepareFrame();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares all solvers to begin simulating a new physics step. This involves
|
||||
/// caching some particle data for interpolation, performing collision detection, among other things.
|
||||
/// </summary>
|
||||
/// <param name="stepDeltaTime"> Duration (in seconds) of the next step.</param>
|
||||
protected void BeginStep(float stepDeltaTime)
|
||||
{
|
||||
using (m_BeginStepPerfMarker.Auto())
|
||||
{
|
||||
// Update colliders right before collision detection:
|
||||
ObiColliderWorld.GetInstance().UpdateColliders();
|
||||
ObiColliderWorld.GetInstance().UpdateRigidbodies(solvers,stepDeltaTime);
|
||||
ObiColliderWorld.GetInstance().UpdateWorld(stepDeltaTime);
|
||||
|
||||
handles.Clear();
|
||||
|
||||
// Kick off all solver jobs:
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
handles.Add(solver.BeginStep(stepDeltaTime));
|
||||
|
||||
// wait for all solver jobs to complete:
|
||||
foreach (IObiJobHandle handle in handles)
|
||||
if (handle != null)
|
||||
handle.Complete();
|
||||
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
solver.ReleaseJobHandles();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Advances the simulation a given amount of time. Note that once BeginStep has been called,
|
||||
/// Substep can be called multiple times.
|
||||
/// </summary>
|
||||
/// <param name="substepDeltaTime"> Duration (in seconds) of the substep.</param>
|
||||
protected void Substep(float stepDeltaTime, float substepDeltaTime, int index)
|
||||
{
|
||||
using (m_SubstepPerfMarker.Auto())
|
||||
{
|
||||
handles.Clear();
|
||||
|
||||
// Kick off all solver jobs:
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
handles.Add(solver.Substep(stepDeltaTime, substepDeltaTime, index));
|
||||
|
||||
// wait for all solver jobs to complete:
|
||||
foreach (IObiJobHandle handle in handles)
|
||||
if (handle != null)
|
||||
handle.Complete();
|
||||
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
solver.ReleaseJobHandles();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps up the current simulation step. This will trigger contact callbacks.
|
||||
/// </summary>
|
||||
protected void EndStep(float substepDeltaTime)
|
||||
{
|
||||
using (m_EndStepPerfMarker.Auto())
|
||||
{
|
||||
// End step: Invokes collision callbacks and notifies actors that the solver step has ended.
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
solver.EndStep(substepDeltaTime);
|
||||
}
|
||||
|
||||
// Write back rigidbody velocity deltas:
|
||||
ObiColliderWorld.GetInstance().UpdateRigidbodyVelocities(solvers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interpolates the previous and current physics states. Should be called right before rendering the current frame.
|
||||
/// </summary>
|
||||
/// <param name="stepDeltaTime"> Duration (in seconds) of the last step taken.</param>
|
||||
/// <param name="stepDeltaTime"> Amount of accumulated (not yet simulated) time.</param>
|
||||
protected void Interpolate(float stepDeltaTime, float accumulatedTime)
|
||||
{
|
||||
using (m_InterpolatePerfMarker.Auto())
|
||||
{
|
||||
foreach (ObiSolver solver in solvers)
|
||||
if (solver != null)
|
||||
solver.Interpolate(stepDeltaTime, accumulatedTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/Updaters/ObiUpdater.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/Updaters/ObiUpdater.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b1bfb6ce01f944a78a3761b5b77d359
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user