// Copyright (C) 2023 Nicholas Maltbie
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using nickmaltbie.TestUtilsUnity;
using UnityEngine;
namespace nickmaltbie.OpenKCC.Environment
{
///
/// Set parameters for a kinematic rigidbody
///
[RequireComponent(typeof(Rigidbody))]
public class FixedRigidbodySet : MonoBehaviour
{
///
/// Reference to unity service for getting basic unity functions.
///
public IUnityService unityService = UnityService.Instance;
///
/// Should continuous movement be used to move the object
/// or discrete steps. uses the MovePosition and MoveRotation api
/// for continus movement otherwise.
///
public bool isContinuous = true;
///
/// Angular velocity of object in degrees per second for each Euclidean axis
///
[SerializeField]
[Tooltip("Angular velocity of object in degrees per second for each Euclidean axis")]
public Vector3 angularVelocity;
///
/// Does this rotation work in local or world space. If true, will rotate in local space.
/// If false will rotate in world space.
///
[SerializeField]
[Tooltip("Does this rotation work in local or world space")]
public bool localRotation;
///
/// Linear velocity of object in units per second for each axis
///
[SerializeField]
[Tooltip("Linear velocity of object in units per second for each axis")]
public Vector3 linearVelocity;
///
/// Does this velocity work in local or world space. If true, will translate in local space.
/// If false will translate in world space.
///
[SerializeField]
[Tooltip("Does this translation work in local or world space.")]
public bool localTranslation;
///
/// Rigidbody for this object
///
protected new Rigidbody rigidbody;
public void Start()
{
rigidbody = GetComponent();
rigidbody.isKinematic = true;
}
public void FixedUpdate()
{
if (linearVelocity.magnitude > 0)
{
// move object by velocity
Vector3 deltaPos = unityService.fixedDeltaTime * linearVelocity;
Vector3 targetPos = (localTranslation && transform.parent != null) ?
transform.parent.position + transform.localPosition + deltaPos :
transform.position + deltaPos;
if (isContinuous)
{
rigidbody.MovePosition(targetPos);
}
else
{
rigidbody.position = targetPos;
}
}
if (angularVelocity.magnitude > 0)
{
// rotate object by rotation
var deltaRotation = Quaternion.Euler(unityService.fixedDeltaTime * angularVelocity);
Quaternion targetRot = (localRotation && transform.parent != null) ?
transform.parent.rotation * transform.localRotation * deltaRotation :
transform.rotation * deltaRotation;
if (isContinuous)
{
rigidbody.MoveRotation(targetRot);
}
else
{
rigidbody.rotation = targetRot;
}
}
}
}
}