Custom movement platform and jitter.

Oxlamon

New member
Hi. I need help.

I wrote custom movement platform:

C#:
public class MovingInterior: MonoBehaviour, IKinematicObject {
    [Tooltip( "Specifies the location that the object should be updated." )]
    [SerializeField] protected KinematicObjectManager.UpdateLocation m_UpdateLocation;

    public KinematicObjectManager.UpdateLocation UpdateLocation => m_UpdateLocation;

    protected Transform m_Transform;
    private Vector3 m_MovePosition;
    private Quaternion m_MoveRotation;

    public int KinematicObjectIndex { get; set; } = -1;

    // Regibody for position and rotation reads
    public Rigidbody readFrom;

    protected void Awake() {

        GameObject m_GameObject = gameObject;
        m_Transform = transform;
        m_MovePosition = m_Transform.position;
        m_MoveRotation = m_Transform.rotation;

        // The Rigidbody is only used to notify Unity that the character isn't static and for collision events. The Rigidbody doesn't control any movement.
        Rigidbody m_Rigidbody = GetComponent<Rigidbody>();
        m_Rigidbody.collisionDetectionMode = CollisionDetectionMode.Discrete;
        m_Rigidbody.isKinematic = true;
        m_Rigidbody.constraints = RigidbodyConstraints.FreezeAll;

        // The GameObject must be on the MovingPlatform layer.
        if(m_GameObject.layer != LayerManager.MovingPlatform) {
            Debug.LogWarning( "Warning: " + m_GameObject.name + " is a moving platform not using the MovingPlatform layer. Please change this layer." );
            m_GameObject.layer = LayerManager.MovingPlatform;
        }   
    }
    
    protected virtual void OnEnable() {
        KinematicObjectIndex = KinematicObjectManager.RegisterKinematicObject( this );
    }
    
    public void Move() {
        if(readFrom) {
            m_MovePosition = readFrom.position;
            m_MoveRotation = readFrom.rotation;
        }

        m_Transform.rotation = m_MoveRotation;
        m_Transform.position = m_MovePosition;
    }
    
    protected virtual void OnDisable() {
        KinematicObjectManager.UnregisterKinematicObject( KinematicObjectIndex );
    }
}

And custom ability: MoveWithShip

C#:
[DefaultStopType( AbilityStopType.Automatic )]
public class MoveWithShip: Ability {
    [Tooltip( "The object that the character should move with." )]
    [SerializeField] protected Transform m_Target;

    public Transform Target {
        get { return m_Target; }
        set {
            m_Target = value;
        }
    }

    public override bool IsConcurrent { get { return true; } }

    public override bool CanStartAbility() {
        if(m_Target == null)
            return false;
        return base.CanStartAbility();
    }

    protected override void AbilityStarted() {
        base.AbilityStarted();

        m_CharacterLocomotion.AlignToGravity = true;
        m_CharacterLocomotion.UpdateLocation = KinematicObjectManager.UpdateLocation.FixedUpdate;
        m_CharacterLocomotion.SetPlatform( m_Target );
        m_Transform.parent = m_Target;
    }

  
    public override bool CanStopAbility() {
        if(m_Target != null) {
            return false;
        }

        return base.CanStopAbility();
    }

    protected override void AbilityStopped( bool force ) {
        base.AbilityStopped( force );

        m_CharacterLocomotion.SetPlatform( null );
    }

    public override void UpdateRotation() {

        var targetNormal = m_Target.up;

        var deltaRotation = Quaternion.Euler( m_CharacterLocomotion.DeltaRotation );
        var rotation = m_Transform.rotation * deltaRotation;
        var proj = (rotation * Vector3.forward) - (Vector3.Dot( (rotation * Vector3.forward), targetNormal )) * targetNormal;
        if(proj.sqrMagnitude > 0.0001f) {
            Quaternion targetRotation;
          
                targetRotation = Quaternion.LookRotation( proj, targetNormal );
          
            deltaRotation = deltaRotation * (Quaternion.Inverse( rotation ) * targetRotation);
            m_CharacterLocomotion.DeltaRotation = deltaRotation.eulerAngles;
        }

        m_CharacterLocomotion.GravityDirection = -targetNormal;
    }
}

Everything in script is simple i think. So next:

0. Character motor and MovingInterior updated in KinematicObjectManager.UpdateLocation.FixedUpdate
1. Add MoveWithShip ability to character. Activate it. Set Target to my platform with MovingInterior script.
2. Create elsewhere gameobject with rigid body and add initial torque to it.
3. Link this rigidbody to MovingInterior.Readfrom
4. Everything worked but character jitter (for MovingInterior set script order before KinematicObject), for platform set layer MovingPlatform

If i create MovingPlatform and set same character to it (and AlignToGround ability activated), everything worked as expected, but i can't find difference between..


thanks in advance for any help.
 
This sounds like it could be a problem with the Script Execution Order. Make sure your custom moving platform is updated around the same time that the regular Moving Platform component is updated.
 
After some investigations.

In the character's UCL:
Motor.UpdateLocation = FixedUpdate; <- important (!)

Platform mover.

C#:
public class MovingInterior: MonoBehaviour, IKinematicObject {
    public Rigidbody readFrom;

    public KinematicObjectManager.UpdateLocation UpdateLocation {
        get { return KinematicObjectManager.UpdateLocation.FixedUpdate; }
    }

    public int KinematicObjectIndex { get; set; }

    public void Move() {
        if(readFrom) {
            this.transform.position = readFrom.position;
            this.transform.rotation = readFrom.rotation;
        }
    }

    public void OnEnable() {
        KinematicObjectIndex = KinematicObjectManager.RegisterKinematicObject( this );
    }

    public void OnDisable() {
        KinematicObjectManager.UnregisterKinematicObject( KinematicObjectIndex );
    }
}

Ability

C#:
[DefaultStopType( AbilityStopType.Automatic )]
public class MoveWithShip: AlignToGravity {
    [Tooltip( "The object that the character should move with." )]
    [SerializeField] protected Transform m_Target;

    public Transform Target {
        get { return m_Target; }
        set {
            m_Target = value;
        }
    }

    public override bool IsConcurrent { get { return true; } }

    public override bool CanStartAbility() {
        if(m_Target == null)
            return false;
        return base.CanStartAbility();
    }

    protected override void AbilityStarted() {
        base.AbilityStarted();
        m_CharacterLocomotion.AlignToGravity = true;
        m_CharacterLocomotion.SetPlatform( m_Target );
    }

  
    public override bool CanStopAbility() {
        if(m_Target != null) {
            return false;
        }
        return base.CanStopAbility();
    }

    protected override void AbilityStopped( bool force ) {
        base.AbilityStopped( force );
        m_CharacterLocomotion.SetPlatform( null );
    }

    public override void UpdateRotation() {
        Rotate( m_Target.up );
        m_CharacterLocomotion.GravityDirection = -m_Target.up;
    }
}

Script order is set by default (not added my own script to it).

aaand everything worked... i think

but moving platform worked fine while in update mode, and character too

as i can see:
KinematicObjectManager

move all platforms
and then move all characters (and their abilities?)

and everything must be worked find, but not.
 
Top