Limit from x y z w to x y

How can i limit the rotation to only the x y axis?

using UnityEngine;
using System.Collections.Generic;


namespace Ardunity
{   

    {
        public bool smoothFollow = true;
        public float limit = 0.1f;  //new limit
        private Quaternion _initRot;
        private IWireInput<Quaternion> _rotation;
        private Quaternion _curRotation;
        private Quaternion _fromRotation;
        private Quaternion _toRotation;
        private float _time;
       
        protected override void Awake()
        {
            base.Awake();
           
            _initRot = transform.localRotation;
            _curRotation = Quaternion.identity;
            _toRotation =  Quaternion.identity;
            _time = 1f;
        }

        // Use this for initialization
        void Start ()
        {
                   
        }
       
        // Update is called once per frame
        void Update ()
        {
            if(_time < 1f && smoothFollow == true)
            {
                _time += Time.deltaTime;
                _curRotation = Quaternion.Lerp(_fromRotation, _toRotation, _time);
            }
            else
                _curRotation = _toRotation;

           // transform.localRotation = _initRot * _curRotation;
            transform.localRotation = Quaternion.Slerp(_initRot * _curRotation, Quaternion.Euler(Vector3.forward), limit);  //Vector3.forward
        }
       
        private void OnRotationChanged(Quaternion q)
        {
            _fromRotation = _toRotation;
            _toRotation =  q;
           
            _time = 0f;
        }
       
        protected override void AddNode(List<Node> nodes)
        {
            base.AddNode(nodes);
           
            nodes.Add(new Node("rotation", "Rotation", typeof(IWireInput<Quaternion>), NodeType.WireFrom, "Input<Quaternion>"));
        }
       
        protected override void UpdateNode(Node node)
        {
            if(node.name.Equals("rotation"))
            {
                node.updated = true;
                if(node.objectTarget == null && _rotation == null)
                    return;
               
                if(node.objectTarget != null)
                {
                    if(node.objectTarget.Equals(_rotation))
                        return;
                }
               
                if(_rotation != null)
                    _rotation.OnWireInputChanged -= OnRotationChanged;
               
                _rotation = node.objectTarget as IWireInput<Quaternion>;
                if(_rotation != null)
                    _rotation.OnWireInputChanged += OnRotationChanged;
                else
                    node.objectTarget = null;
               
                return;
            }
           
            base.UpdateNode(node);
        }
    }
}

I have tried a bit but Quaternio over sized my brain :slight_smile:

Hi, I’ve used two nested transforms rotating one of them on Y axis only and it’s child on X axiso only. It works quite well for me.
Cheers.

No that is not working for me, because i read the RAW data from a Arduino MPU 6050 Gyroscope.
First i have limit the rotation with slerp, so the physic engine do not struggle.

I have qy qx qz and qw.

My idea was to create a newVector and set the qz and qw to zero.
But when i do this the rotation runs in trouble:

i have also tried to attach a rigid body and fix the z rotation, but the values are protected, so i need to do this in code.



I thought about this:

transform.localRotation = Quaternion.Slerp(_initRot * _curRotation, Quaternion.Euler(transform.localRotation.eulerAngles.x,transform.localRotation.y, lockZ), limit);

but it is not working :frowning:

Just explaining this so I am sure I understand what you are doing. You have some GameObject in your Unity Scene. You have an realworld gyroscope that is moving around in a all 3 axis. You read that data and copy it so your Unity Object rotates the same way. Now you would like to limit this so it only rotates forward and pans around. No spinning around the z- Axis?

float initialZ;

void Awake()
{
       initialZ = transform.eulerAngles.z;
}

void Update()
{
         // All your code to get a rotations from the Arduiino
         Quaternion rotation  = // your code to get the rotation from the gyroscope
         Vector3 eulerAngles = rotation.eulerAngles;
         eulerAngles.z = initialZ;
         rotation = Quaternion.Euler(eulerAngles);
}

Now you have just the x,y components of your rotations with the original z rotations from the program start.

thanks but isnt working so:

        public bool smoothFollow = true;
        public float limit = 0.1f;  //new limit
        public float initialZ;
        private Quaternion _initRot;
        private IWireInput<Quaternion> _rotation;
        private Quaternion _curRotation;
        private Quaternion _fromRotation;
        private Quaternion _toRotation;
        private float _time;
       
        protected override void Awake()
        {
            base.Awake();
           
            _initRot = transform.localRotation;
            _curRotation = Quaternion.identity;
            _toRotation =  Quaternion.identity;
            _time = 1f;
            initialZ = transform.eulerAngles.z;
        }

        // Use this for initialization
        void Start ()
        {
                   
        }
       
        // Update is called once per frame
        void Update ()
        {
            if(_time < 1f && smoothFollow == true)
            {
                _time += Time.deltaTime;
                _curRotation = Quaternion.Lerp(_fromRotation, _toRotation, _time);
            }
            else
                _curRotation = _toRotation;

            //transform.localRotation = _initRot * _curRotation;
           // transform.localRotation = Quaternion.Slerp(_initRot * _curRotation, Quaternion.Euler(Vector3.forward), limit);  //New Limit

            Quaternion rotation = transform.localRotation = Quaternion.Slerp(_initRot * _curRotation, Quaternion.Euler(Vector3.forward), limit);  //New Limit
            Vector3 eulerAngles = rotation.eulerAngles;
            eulerAngles.z = initialZ;
            rotation = Quaternion.Euler(eulerAngles);

i have still rotation on the Z axis

Its because your copying the transforms local rotation into a a variable called rotation. then setting the z value on that rotation but never sticking it back into the transform.

  Quaternion rotation = Quaternion.Slerp(_initRot * _curRotation, Quaternion.Euler(Vector3.forward), limit);  //New Limit
            Vector3 eulerAngles = rotation.eulerAngles;
            eulerAngles.z = initialZ;
            rotation = Quaternion.Euler(eulerAngles);
transform.localRotation = rotation;

Ah know i understand!
It works great! Thank you.
I need to go deeper in this.

But I’m not sure the above code will work exactly like you want. I’d do it like this:
Modified GryoCode

using UnityEngine;
using System.Collections.Generic;


namespace Ardunity
{
    public class WasNotPosted : MonoBehaviour
    {
        public bool smoothFollow = true;
        public float limit = 0.1f;  //new limit
        private Quaternion _initRot;
        private IWireInput<Quaternion> _rotation;
        private Quaternion _curRotation;
        private Quaternion _fromRotation;
        private Quaternion _toRotation;
        private float _time;
        private float initialZ;

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

            _initRot = transform.localRotation;
            _curRotation = transform.localRotation;
            _toRotation = Quaternion.identity;
            _time = 1f;
            initialZ = transform.localRotation.eulerAngles.z;
        }

        // Use this for initialization
        void Start()
        {

        }

        // Update is called once per frame
        void Update()
        {
            if (_time < 1f && smoothFollow == true)
            {
                _time += Time.deltaTime;
                _curRotation = Quaternion.SLerp(_fromRotation, _toRotation, _time);
            }
            else
                _curRotation = _toRotation;

            // transform.localRotation = _initRot * _curRotation;
            transform.localRotation = _curRotation;
        }

        private void OnRotationChanged(Quaternion q)
        {
            _fromRotation = _curRotation;
            Vector3 eulerAngles = q.eulerAngles;
            eulerAngles.z = initialZ;
            _toRotation = Quaternion.Euler(eulerAngles);

            _time = 0f;
        }

        protected override void AddNode(List<Node> nodes)
        {
            base.AddNode(nodes);

            nodes.Add(new Node("rotation", "Rotation", typeof(IWireInput<Quaternion>), NodeType.WireFrom, "Input<Quaternion>"));
        }

        protected override void UpdateNode(Node node)
        {
            if (node.name.Equals("rotation"))
            {
                node.updated = true;
                if (node.objectTarget == null && _rotation == null)
                    return;

                if (node.objectTarget != null)
                {
                    if (node.objectTarget.Equals(_rotation))
                        return;
                }

                if (_rotation != null)
                    _rotation.OnWireInputChanged -= OnRotationChanged;

                _rotation = node.objectTarget as IWireInput<Quaternion>;
                if (_rotation != null)
                    _rotation.OnWireInputChanged += OnRotationChanged;
                else
                    node.objectTarget = null;

                return;
            }

            base.UpdateNode(node);
        }
    }
}

I moved the removal of the Z axis rotation to the OnRotationChanged EvenHandler
Also i changed your _fromRotation to equal the current rotation, not the former _toRotation. This makes more sense because if we are in the middle of Slerping to the _toRotation and the user moves again before we get there. We don’t want to instantly jump to our former target then start Slerping again. We just want to start SLerping from where we are to the new target.

Edit: Had a bug in the code setting _toRotation. Fixed now if you copied it before this edit need to change to the new version.

hmm i try this out, but i see no jumping or jitter.
But thanks.
When i release this stuff in 2-3 weeks, i do this for free. So if you have a “Wackel board” and Arduino with MPU you can play it.
currently my feet are burning by testing :slight_smile: