mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
2D Physics and script improvements
- fixed time step - Fixed crash caused by physics script callback being registered in simulation mode - Moved 2D Physics config to file - Finally gave up on the attempt to keep X and Y rotation when applying new Z-rotation from 2D rigidbody to transform and now I can sleep well - Streamlined starting and stopping of scenes - Scripts: execute all inits and OnCreates before OnUpdate
This commit is contained in:
@@ -919,8 +919,7 @@ namespace GlitchyEditor
|
|||||||
/// @param startSimulation If set to true, the physics simulation will be initialized for the given scene.
|
/// @param startSimulation If set to true, the physics simulation will be initialized for the given scene.
|
||||||
private void SetActiveScene(Scene scene, bool startRuntime, bool startSimulation, PlayMode? newPlayMode = null)
|
private void SetActiveScene(Scene scene, bool startRuntime, bool startSimulation, PlayMode? newPlayMode = null)
|
||||||
{
|
{
|
||||||
_activeScene?.StopRuntime();
|
_activeScene?.Stop();
|
||||||
_activeScene?.StopSimulation();
|
|
||||||
|
|
||||||
if (newPlayMode != null)
|
if (newPlayMode != null)
|
||||||
{
|
{
|
||||||
@@ -939,11 +938,7 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
if (scene != null)
|
if (scene != null)
|
||||||
{
|
{
|
||||||
if (startRuntime)
|
scene.Start(startRuntime, startSimulation);
|
||||||
scene.StartRuntime();
|
|
||||||
|
|
||||||
if (startSimulation)
|
|
||||||
scene.StartSimulation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetReference!(_activeScene, scene);
|
SetReference!(_activeScene, scene);
|
||||||
@@ -1058,10 +1053,7 @@ namespace GlitchyEditor
|
|||||||
/// Sets the current editor scene
|
/// Sets the current editor scene
|
||||||
private void SetEditorScene(Scene scene, Dictionary<UUID, SerializedObject> serializedObjects = null)
|
private void SetEditorScene(Scene scene, Dictionary<UUID, SerializedObject> serializedObjects = null)
|
||||||
{
|
{
|
||||||
if (_editorScene != null)
|
_editorScene?.Stop();
|
||||||
{
|
|
||||||
_editorScene.StopRuntime();
|
|
||||||
}
|
|
||||||
|
|
||||||
SetReference!(_editorScene, scene);
|
SetReference!(_editorScene, scene);
|
||||||
_editor.CurrentScene = _editorScene;
|
_editor.CurrentScene = _editorScene;
|
||||||
@@ -1069,7 +1061,7 @@ namespace GlitchyEditor
|
|||||||
|
|
||||||
if (_editorScene != null)
|
if (_editorScene != null)
|
||||||
{
|
{
|
||||||
_editorScene.StartRuntime();
|
_editorScene.Start(startRuntime: true, startSimulation: false);
|
||||||
|
|
||||||
if (serializedObjects != null)
|
if (serializedObjects != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -731,8 +731,7 @@ static class ScriptGlue
|
|||||||
{
|
{
|
||||||
Scene scene = ScriptEngine.Context;
|
Scene scene = ScriptEngine.Context;
|
||||||
|
|
||||||
var box2DGravity = Box2D.World.GetGravity(scene.[Friend]_physicsWorld2D);
|
gravity = scene.Physics2DSettings.Gravity;
|
||||||
gravity = *(float2*)&box2DGravity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RegisterCall("ScriptGlue::Physics2D_SetGravity")]
|
[RegisterCall("ScriptGlue::Physics2D_SetGravity")]
|
||||||
@@ -740,8 +739,7 @@ static class ScriptGlue
|
|||||||
{
|
{
|
||||||
Scene scene = ScriptEngine.Context;
|
Scene scene = ScriptEngine.Context;
|
||||||
|
|
||||||
#unwarn
|
scene.Physics2DSettings.Gravity = gravity;
|
||||||
Box2D.World.SetGravity(scene.[Friend]_physicsWorld2D, gravity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Physics2D
|
#endregion Physics2D
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using GlitchyEngine.Math;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.World;
|
||||||
|
|
||||||
|
struct Physics2DSettings
|
||||||
|
{
|
||||||
|
private Scene _scene;
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
private Box2D.b2World* _physicsWorld => _scene.[Friend]_physicsWorld2D;
|
||||||
|
|
||||||
|
public float2 _gravity = .(0.0f, -9.8f);
|
||||||
|
|
||||||
|
public float2 Gravity
|
||||||
|
{
|
||||||
|
get => _gravity;
|
||||||
|
set mut
|
||||||
|
{
|
||||||
|
if (all(_gravity == value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_gravity = value;
|
||||||
|
|
||||||
|
if (_physicsWorld != null)
|
||||||
|
Box2D.World.SetGravity(_physicsWorld, _gravity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int32 VelocityIterations = 6;
|
||||||
|
public int32 PositionIterations = 2;
|
||||||
|
public int32 ParticleIterations = 2;
|
||||||
|
|
||||||
|
public this(Scene scene)
|
||||||
|
{
|
||||||
|
_scene = scene;
|
||||||
|
}
|
||||||
|
}
|
||||||
+152
-109
@@ -25,6 +25,13 @@ namespace GlitchyEngine.World
|
|||||||
b2ContactListener _contactListener;
|
b2ContactListener _contactListener;
|
||||||
b2Draw draw = .();
|
b2Draw draw = .();
|
||||||
|
|
||||||
|
private float _fixedDeltaTime = 1.0f / 60.0f;
|
||||||
|
|
||||||
|
private Physics2DSettings _physics2dSettings = .(this);
|
||||||
|
|
||||||
|
[Inline]
|
||||||
|
public ref Physics2DSettings Physics2DSettings => ref _physics2dSettings;
|
||||||
|
|
||||||
private Dictionary<Type, function void(Entity entity, Type componentType, void* component)> _onComponentAddedHandlers = new .() ~ delete _;
|
private Dictionary<Type, function void(Entity entity, Type componentType, void* component)> _onComponentAddedHandlers = new .() ~ delete _;
|
||||||
|
|
||||||
private uint32 _viewportWidth, _viewportHeight;
|
private uint32 _viewportWidth, _viewportHeight;
|
||||||
@@ -196,8 +203,6 @@ namespace GlitchyEngine.World
|
|||||||
target.AddComponent<TComponent>(*component);
|
target.AddComponent<TComponent>(*component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b2Vec2 _gravity2D = .(0.0f, -9.8f);
|
|
||||||
|
|
||||||
static b2BodyType GetBox2DBodyType(Rigidbody2DComponent.BodyType bodyType)
|
static b2BodyType GetBox2DBodyType(Rigidbody2DComponent.BodyType bodyType)
|
||||||
{
|
{
|
||||||
@@ -215,7 +220,37 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartRuntime()
|
/**
|
||||||
|
* Starts the scene.
|
||||||
|
* @param startRuntime If true, the script runtime will be started.
|
||||||
|
* @param startSimulation If true, the physics engine will be started.
|
||||||
|
*/
|
||||||
|
public void Start(bool startRuntime, bool startSimulation)
|
||||||
|
{
|
||||||
|
if (startSimulation)
|
||||||
|
StartSimulation();
|
||||||
|
|
||||||
|
if (startRuntime)
|
||||||
|
{
|
||||||
|
StartRuntime();
|
||||||
|
|
||||||
|
if (startSimulation)
|
||||||
|
{
|
||||||
|
SetupPhysicsCallbacks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the scene by shutting down the script runtime and physics simulation.
|
||||||
|
*/
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
StopRuntime();
|
||||||
|
StopSimulation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartRuntime()
|
||||||
{
|
{
|
||||||
ScriptEngine.StartRuntime(this);
|
ScriptEngine.StartRuntime(this);
|
||||||
|
|
||||||
@@ -228,16 +263,16 @@ namespace GlitchyEngine.World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopRuntime()
|
private void StopRuntime()
|
||||||
{
|
{
|
||||||
ScriptEngine.StopRuntime();
|
ScriptEngine.StopRuntime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartSimulation()
|
private void StartSimulation()
|
||||||
{
|
{
|
||||||
// TODO: Add Setting for the user to define whether Physics will be initialized or not?
|
// TODO: Add Setting for the user to define whether Physics will be initialized or not?
|
||||||
|
|
||||||
_physicsWorld2D = World.Create(_gravity2D);
|
_physicsWorld2D = World.Create(_physics2dSettings.Gravity);
|
||||||
|
|
||||||
draw.drawPolygonCallback = (vertices, vertexCount, color, userData) =>
|
draw.drawPolygonCallback = (vertices, vertexCount, color, userData) =>
|
||||||
{
|
{
|
||||||
@@ -290,8 +325,6 @@ namespace GlitchyEngine.World
|
|||||||
World.SetDebugDrawFlags(_physicsWorld2D, .e_shapeBit);
|
World.SetDebugDrawFlags(_physicsWorld2D, .e_shapeBit);
|
||||||
|
|
||||||
InitPhysics2D();
|
InitPhysics2D();
|
||||||
|
|
||||||
SetupPhysicsCallbacks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupPhysicsCallbacks()
|
private void SetupPhysicsCallbacks()
|
||||||
@@ -593,7 +626,7 @@ namespace GlitchyEngine.World
|
|||||||
polygonCollider.RuntimeFixture = fixture;
|
polygonCollider.RuntimeFixture = fixture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StopSimulation()
|
private void StopSimulation()
|
||||||
{
|
{
|
||||||
if (_physicsWorld2D == null)
|
if (_physicsWorld2D == null)
|
||||||
return;
|
return;
|
||||||
@@ -623,6 +656,114 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
private append List<ScriptInstance> _destroyScriptQueue = .();
|
private append List<ScriptInstance> _destroyScriptQueue = .();
|
||||||
|
|
||||||
|
float physicsDelta = 0;
|
||||||
|
|
||||||
|
private void UpdatePhysics(GameTime gameTime)
|
||||||
|
{
|
||||||
|
physicsDelta += gameTime.DeltaTime;
|
||||||
|
|
||||||
|
while (physicsDelta > _fixedDeltaTime)
|
||||||
|
{
|
||||||
|
physicsDelta -= _fixedDeltaTime;
|
||||||
|
|
||||||
|
Debug.Profiler.ProfileScope!("2D Physics Iteration");
|
||||||
|
|
||||||
|
Box2D.World.Step(_physicsWorld2D, _fixedDeltaTime, Physics2DSettings.VelocityIterations, Physics2DSettings.PositionIterations, Physics2DSettings.ParticleIterations);
|
||||||
|
|
||||||
|
// Retrieve transform from Box2D
|
||||||
|
for (var entry in _ecsWorld.Enumerate<Rigidbody2DComponent>())
|
||||||
|
{
|
||||||
|
Entity entity = .(entry.Entity, this);
|
||||||
|
|
||||||
|
var transform = entity.Transform;
|
||||||
|
var rigidbody = entry.Component;
|
||||||
|
|
||||||
|
b2Body* body = rigidbody.RuntimeBody;
|
||||||
|
b2Vec2 position = Box2D.Body.GetPosition(body);
|
||||||
|
float angle = Box2D.Body.GetAngle(body);
|
||||||
|
b2Transform bodyTransform = Box2D.Body.GetTransform(body);
|
||||||
|
|
||||||
|
float cos = sqrt((1 + bodyTransform.q.c) / 2);
|
||||||
|
float sin = sqrt((1 - bodyTransform.q.c) / 2) * sign(bodyTransform.q.s);
|
||||||
|
|
||||||
|
Quaternion rotation = .(0, 0, sin, cos)..Normalize();
|
||||||
|
|
||||||
|
if (entity.Parent != null)
|
||||||
|
{
|
||||||
|
Matrix worldToParent = entity.Parent.Value.Transform.WorldTransform.Invert();
|
||||||
|
|
||||||
|
float4 newLocalPosition = worldToParent * float4(position, 0, 1);
|
||||||
|
transform.Position = float3(newLocalPosition.XY, transform.Position.Z);
|
||||||
|
|
||||||
|
// TODO: when the parent of the rigidbody-entity is rotated, the rotation is applied wrong...
|
||||||
|
Matrix.Decompose(worldToParent, let p, var worldToParentRotation, let s);
|
||||||
|
//Quaternion newLocalRotation = (worldToParentRotation..Normalize() * rotation..Normalize())..Normalize();
|
||||||
|
//Quaternion newLocalRotation = (rotation * worldToParentRotation..Normalize())..Normalize();
|
||||||
|
//Quaternion newLocalRotation = (worldToParentRotation * rotation)..Normalize();
|
||||||
|
Quaternion newLocalRotation = rotation..Normalize();
|
||||||
|
//Quaternion newLocalRotation = Quaternion.FromEulerAngles(0, 0, angle)..Normalize();
|
||||||
|
// TODO: when the parent has rotation on X or Y everything breaks even more...
|
||||||
|
//transform.Rotation = (Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0)..Normalize() * newLocalRotation)..Normalize();//(newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize();
|
||||||
|
//transform.Rotation = ((transform.Rotation..Normalize() * Quaternion.FromEulerAngles(0, 0, transform.RotationEuler.Z)..Normalize())..Normalize() * newLocalRotation)..Normalize();//(newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize();
|
||||||
|
transform.Rotation = (newLocalRotation)..Normalize();//(newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transform.Position = .(position.x, position.y, transform.Position.Z);
|
||||||
|
transform.Rotation = rotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Execute Fixed-Updates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateScripts(GameTime gameTime, UpdateMode mode)
|
||||||
|
{
|
||||||
|
Debug.Profiler.ProfileScope!("Update scripts");
|
||||||
|
|
||||||
|
// all OnCreates have to be executed before the first OnUpdate!
|
||||||
|
|
||||||
|
// TODO: This could also be handled with a queue!
|
||||||
|
// Init and OnCreate
|
||||||
|
for (let (entity, script) in _ecsWorld.Enumerate<ScriptComponent>())
|
||||||
|
{
|
||||||
|
if (script.IsCreated)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!script.IsInitialized)
|
||||||
|
ScriptEngine.InitializeInstance(Entity(entity, this), script);
|
||||||
|
|
||||||
|
// Skip OnCreate and OnUpdate invocation if we didn't create an instance
|
||||||
|
// (happens, if script component has no script class associated)
|
||||||
|
// Also skip if we are in edit mode and the class doesn't have the RunInEditMode-Attribute
|
||||||
|
if (script.Instance == null || (mode.HasFlag(.EditMode) && !script.Instance.ScriptClass.RunInEditMode))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
script.Instance.InvokeOnCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnUpdate
|
||||||
|
for (let (entity, script) in _ecsWorld.Enumerate<ScriptComponent>())
|
||||||
|
{
|
||||||
|
if (script.Instance == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO: When the entity is destroyed in OnCreate it's OnUpdate will still be called. Is this fine?
|
||||||
|
// It would require that we somehow track whether the entity is to be deleted. We technically have this info but would probably need
|
||||||
|
// some faster way. If we for some reason ever happen to implement such a fast way we can check for planned deletion here (or after on Create and just continue;).
|
||||||
|
|
||||||
|
// Update the script, if we aren't in editor or it has RunInEditMode-Attribute
|
||||||
|
if (!mode.HasFlag(.EditMode) || script.Instance.ScriptClass.RunInEditMode)
|
||||||
|
{
|
||||||
|
if (_updateBlockList.Contains(entity))
|
||||||
|
_updateBlockList.Remove(entity);
|
||||||
|
else
|
||||||
|
script.Instance.InvokeOnUpdate(gameTime.DeltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Update(GameTime gameTime, UpdateMode mode)
|
public void Update(GameTime gameTime, UpdateMode mode)
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileRendererFunction!();
|
Debug.Profiler.ProfileRendererFunction!();
|
||||||
@@ -631,52 +772,7 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
if (mode.HasFlag(.Scripts))
|
if (mode.HasFlag(.Scripts))
|
||||||
{
|
{
|
||||||
Debug.Profiler.ProfileScope!("Update scripts");
|
UpdateScripts(gameTime, mode);
|
||||||
|
|
||||||
// Run scripts
|
|
||||||
for (let (entity, script) in _ecsWorld.Enumerate<ScriptComponent>())
|
|
||||||
{
|
|
||||||
ScriptInstance scriptInstance = null;
|
|
||||||
|
|
||||||
if (!script.IsCreated)
|
|
||||||
{
|
|
||||||
if (!script.IsInitialized)
|
|
||||||
ScriptEngine.InitializeInstance(Entity(entity, this), script);
|
|
||||||
|
|
||||||
scriptInstance = script.Instance;
|
|
||||||
|
|
||||||
// Skip OnCreate and OnUpdate invocation if we didn't create an instance
|
|
||||||
// (happens, if script component has no script class associated)
|
|
||||||
// Also skip if we are in edit mode and the class doesn't have the RunInEditMode-Attribute
|
|
||||||
if (scriptInstance == null || (mode.HasFlag(.EditMode) && !scriptInstance.ScriptClass.RunInEditMode))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// OnCreate can remove the script, so we have to make sure that we have a reference and it survives.
|
|
||||||
// Todo: Technically we can rely on scriptInstance surviving a delete because we always defer deletion (unless we might not?)
|
|
||||||
scriptInstance.AddRef();
|
|
||||||
|
|
||||||
scriptInstance.InvokeOnCreate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scriptInstance = script.Instance..AddRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: When the entity is destroyed in OnCreate it's OnUpdate will still be called. Is this fine?
|
|
||||||
// It would require that we somehow track whether the entity is to be deleted. We technically have this info but would probably need
|
|
||||||
// some faster way. If we for some reason ever happen to implement such a fast way we can check for planned deletion here (or after on Create and just continue;).
|
|
||||||
|
|
||||||
// Update the script, if we aren't in editor or it has RunInEditMode-Attribute
|
|
||||||
if (!mode.HasFlag(.EditMode) || scriptInstance.ScriptClass.RunInEditMode)
|
|
||||||
{
|
|
||||||
if (_updateBlockList.Contains(entity))
|
|
||||||
_updateBlockList.Remove(entity);
|
|
||||||
else
|
|
||||||
scriptInstance.InvokeOnUpdate(gameTime.DeltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptInstance?.ReleaseRef();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_destroyScriptQueue.IsEmpty)
|
if (!_destroyScriptQueue.IsEmpty)
|
||||||
@@ -705,60 +801,7 @@ namespace GlitchyEngine.World
|
|||||||
|
|
||||||
if (mode.HasFlag(.Physics))
|
if (mode.HasFlag(.Physics))
|
||||||
{
|
{
|
||||||
// Update 2D physics
|
UpdatePhysics(gameTime);
|
||||||
{
|
|
||||||
const int32 velocityIterations = 6;
|
|
||||||
const int32 positionIterations = 2;
|
|
||||||
const int32 particleIterations = 2;
|
|
||||||
|
|
||||||
Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations);
|
|
||||||
|
|
||||||
// Retrieve transform from Box2D
|
|
||||||
for (var entry in _ecsWorld.Enumerate<Rigidbody2DComponent>())
|
|
||||||
{
|
|
||||||
Entity entity = .(entry.Entity, this);
|
|
||||||
|
|
||||||
var transform = entity.Transform;
|
|
||||||
var rigidbody = entry.Component;
|
|
||||||
|
|
||||||
b2Body* body = rigidbody.RuntimeBody;
|
|
||||||
b2Vec2 position = Box2D.Body.GetPosition(body);
|
|
||||||
float angle = Box2D.Body.GetAngle(body);
|
|
||||||
b2Transform bodyTransform = Box2D.Body.GetTransform(body);
|
|
||||||
|
|
||||||
float cos = sqrt((1 + bodyTransform.q.c) / 2);
|
|
||||||
float sin = sqrt((1 - bodyTransform.q.c) / 2) * sign(bodyTransform.q.s);
|
|
||||||
|
|
||||||
Quaternion rotation = .(0, 0, sin, cos)..Normalize();
|
|
||||||
|
|
||||||
if (entity.Parent != null)
|
|
||||||
{
|
|
||||||
Matrix worldToParent = entity.Parent.Value.Transform.WorldTransform.Invert();
|
|
||||||
|
|
||||||
float4 newLocalPosition = worldToParent * float4(position, 0, 1);
|
|
||||||
transform.Position = float3(newLocalPosition.XY, transform.Position.Z);
|
|
||||||
|
|
||||||
// TODO: when the parent of the rigidbody-entity is rotated, the rotation is applied wrong...
|
|
||||||
Matrix.Decompose(worldToParent, let p, var worldToParentRotation, let s);
|
|
||||||
//Quaternion newLocalRotation = (worldToParentRotation..Normalize() * rotation..Normalize())..Normalize();
|
|
||||||
//Quaternion newLocalRotation = (rotation * worldToParentRotation..Normalize())..Normalize();
|
|
||||||
//Quaternion newLocalRotation = (worldToParentRotation * rotation)..Normalize();
|
|
||||||
Quaternion newLocalRotation = rotation..Normalize();
|
|
||||||
//Quaternion newLocalRotation = Quaternion.FromEulerAngles(0, 0, angle)..Normalize();
|
|
||||||
// TODO: when the parent has rotation on X or Y everything breaks even more...
|
|
||||||
//transform.Rotation = (Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0)..Normalize() * newLocalRotation)..Normalize();//(newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize();
|
|
||||||
//transform.Rotation = ((transform.Rotation..Normalize() * Quaternion.FromEulerAngles(0, 0, transform.RotationEuler.Z)..Normalize())..Normalize() * newLocalRotation)..Normalize();//(newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize();
|
|
||||||
transform.Rotation = (newLocalRotation)..Normalize();//(newLocalRotation * Quaternion.FromEulerAngles(transform.RotationEuler.Y, transform.RotationEuler.X, 0))..Normalize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transform.Position = .(position.x, position.y, transform.Position.Z);
|
|
||||||
//transform.RotationEuler = .(transform.RotationEuler.XY, angle);
|
|
||||||
//transform.RotationEuler = .(0, 0, angle);
|
|
||||||
transform.Rotation = normalize(rotation * normalize(Quaternion.FromEulerAngles(transform.RotationEuler.X, transform.RotationEuler.Y, 0)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user