Forum rules - please read before posting.

Possible to limit the rotation scope of an NPC/Sprite?

If I wanted a 2d NPC in a 3d environment to face the player only within a scope of 90 degrees, so they stop turning after they reach 0 or 90, is there an option for that somewhere?

Thanks.

Comments

  • I'm afraid I'm not too clear on your meaning. As this is a visual question, could you share screenshots / mockup to describe the situation?

  • Hopefully this is clear. I actually meant to type 270 degrees as seen in this example.

  • It'd be possible with a custom script, though the dealing of angles / rotations would be a bit tricky.

    If you use a script that's set to execute after AC's Char script, updates made to the sprite child's Transform made in LateUpdate will be called after AC. You can use this to manipulate the sprite child to your intended orientation.

    The below script'll probably need correcting on your end to get the behaviour correct, but it'll serve as a base that lets you override the sprite rotation:

    using UnityEngine;
    using AC;
    
    [DefaultExecutionOrder (10)]
    public class LimitSpriteAngle : MonoBehaviour
    {
    
        public AC.Char character;
        public Vector3 midAngle = new Vector3 (0f, 0f, 1f);
        public float angleLimit = 90f;
    
        private void LateUpdate ()
        {
            float signedAngle = Vector3.SignedAngle (character.spriteChild.forward, midAngle, Vector3.up);
            if (signedAngle < -angleLimit)
            {
                Quaternion rot = Quaternion.AngleAxis (180f + angleLimit, Vector3.up);
                character.spriteChild.rotation = rot * Quaternion.Euler (midAngle);
            }
            else if (signedAngle > angleLimit)
            {
                Quaternion rot = Quaternion.AngleAxis (180f - angleLimit, Vector3.up);
                character.spriteChild.rotation = rot * Quaternion.Euler (midAngle);
            }
        }
    
    }
    
  • Thanks for that Chris. I will play with it. Thinking of my needs for this in a different way, there may be a simplier solution.

    Is it possible to get the NPC to rotate only to face the players position and not to rotate as the player rotates?

    (To expand, currently if the player is standing next to the npc and looks around, the npc rotates in sync, not only when the player is transforming)

  • When a sprite-based character is used in a 3D scene, they'll have an additional Rotate sprite to field in their Inspector. This can be used to control whether they face the camera's facing direction, or its relative position.

  • Ok that almost gets what I need. However I wish the sprite to rotate to face the player only on its Y axis, but currently it is rotating on the Z and X axis also. I have already ticked the Freeze Rotation for Z and X on its Rigidbody, but that doesn't help.

  • Try this:

    using UnityEngine;
    using AC;
    
    [DefaultExecutionOrder (10)]
    public class LimitSpriteAngle : MonoBehaviour
    {
    
        public AC.Char character;
    
        private void LateUpdate ()
        {
            Vector3 spriteEuler = character.spriteChild.localEulerAngles;
            spriteEuler.x = 0f;
            character.spriteChild.localEulerAngles = spriteEuler;
        }
    
    }
    
  • Thanks Chris. I'm using both scripts on the sprite and they are doing the job.

    An unforseen issue is that if I rotate the gameobject the sprite is a child of, then run the game, the sprite no longer rotates as expected and I assume I'd have to change settings/scripts to get it working again. Is it possible to adjust your scripts so that the rotation only reads and applies the axis' and angles to the sprite locally and wont be affected if its parent gameobject is rotated in the world?

  • The "Rotate sprites to" mention was as an alternative to the first script - if you use that field and the second script, and remove the first, does it then work?

    As both scripts affect the rotation, there's a conflict - they'd likely have to be merged to have them run together properly.

  • Tested on 4 prefab instances of the same Sprite/NPC, each facing 1 of 4 directions, 0, 90, 180, 270. The script's variables were setup to work with one, which I then applied (override) to the prefab. Checking that all the instances then reverted to that.

    So I can confirm that having Rotate Sprites to set to Relative position to camera and the first script (limiting the angle) disabled and the second (limiting the axis) active, all 4 Sprites work as intended.

    However I do need to limit the angle as well as the axis so:

    having Rotate Sprites to set to Relative position to camera and the first script (limiting the angle) active and the second (limiting the axis) active, The sprite whose directional facing I setup the variables on initially, works perfectly with axis and angle limitations. The other 3 sprites (which face other directions) exihibit behaviour I'd expect if the Angle Limit was referencing World coordinates for rotation and not Local, e.g: one rotates a bit, but not the full degrees set, one doesn't rotate at all etc...

    If I take any of these 3 Sprites and rotate to the same direction as the first, they work perfectly. So I think the scripts work fine along side each other, but the Limit Angles one needs some adjustment.

    Appriciate your help Chris.

  • Try sticking this on the end of the first script's LateUpdate function:

    else
        {
        Quaternion rot = Quaternion.AngleAxis (180f - signedAngle, Vector3.up);
            character.spriteChild.rotation = rot * Quaternion.Euler (midAngle);
        }
    

    That should cause Rotate sprites to to be bypassed completely, reducing the number of factors here. It should then be a case of tweaking the script to suit.

  • Done that. Unfortunately did not fix the issue. Same behaviour as last time.

    If it helps, I don't actually need these sprites to be npcs, I just need the rotate to player functionality with the limitations I mentioned.

  • edited January 2023

    Following on from that, if I Duplicate any of the sprites in the scene (including the working one), the copy will have the axis limit (and conversely rotation) changed. If I then Duplicate that copy, the axis limit changes back to its original.. and so on.

  • If they don't need to be NPCs, then it'll be easier because you don't have to nest your sprite as a child of another object.

    If your script is in total control of the rotation, you can use Unity's "Camera.main.transform" variable as reference for where the Player camera is - but the script itself wouldn't involve AC and this becomes a more general Unity topic.

    Rotations and such are tricky to get exactly right, but the Unity forums should be able to help better than I can.

  • No worries. Thanks Chris.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.