Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question How to rotate a sprite with C#?

Discussion in 'Scripting' started by CovalenceSTU, Jun 2, 2020.

  1. CovalenceSTU

    CovalenceSTU

    Joined:
    Sep 10, 2018
    Posts:
    63
    I've been trying to make a script that tracks the speed of the player's car and displays it on text and a gauge. The tracking and the text work, but I can't figure out how to make the gauge needle rotate.

    Here's my code:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class CarMPHDisplay : MonoBehaviour {
    6.      public Text MphText;
    7.      public Rigidbody Car;
    8.      public Sprite Needle;
    9.      private float carSpeed;
    10.    
    11.      public IEnumerator setup() {
    12.          Car = GetComponent<Rigidbody>();
    13.          yield return null;
    14.      }
    15.  
    16.      void Update() {
    17.          carSpeed = Car.velocity.magnitude * 2.237f; //speed in MPH
    18.          MphText.text = Mathf.RoundToInt(carSpeed) + "";
    19.          Needle.transform.Rotate(0f, 0f, -carSpeed * 1.5f, Space.World);
    20.      }
    21. }
    I get this error: CarMPHDisplay.cs(19,11): error CS1061: 'Sprite' does not contain a definition for 'transform' and no accessible extension method 'transform' accepting a first argument of type 'Sprite' could be found (are you missing a using directive or an assembly reference?)

    I've tried using Transform/rectTransform/RectTransform instead of "transform" and a few other possible solutions I saw, but none of them worked.

    How can I make my script rotate the sprite?
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Sprites aren't components, they're assets. If you're using UnityEngine.UI, then the component that displays the sprite is probably an Image. If you had the Image, you could access the related Transform and rotate it, but a Sprite isn't attached to any specific GameObject.

    There's probably some way that you could generate an entirely new Sprite that looks like a rotated version of the original Sprite based on modifying pixels, but if you want to rotate the Transform that's displaying the Sprite--and I think that is probably what you want to do--then you need to start with a reference to that GameObject or one of its Components, not the asset being displayed.
     
    Kurt-Dekker likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Coupla things... a Sprite is the thing you are showing. It is formed by the editor in response to you supplying a texture, and optionally a cutout area for that sprite. That's the needle.

    A SpriteRenderer is a component that plugs into a GameObject and takes a Sprite and renders it.

    A Transform is ANOTHER type of component that plugs into a GameObject.

    Handily if you have a Transform or a GameObject or a SpriteRenderer, you can get to all of them through shortcuts.

    To fill in via the inspector, dragging itself onto itself:

    Code (csharp):
    1. public SpriteRenderer MySpriteRenderer;
    and then in code:

    Code (csharp):
    1. GameObject go = MySpriteRenderer.gameObject;  // shortcut
    2.  
    3. Transform tr = MySpriteRenderer.transform;  // anotehr shortcut
    For the purpose of a speedo, you probably want to use something like Mathf.Lerp() to smoothly transition from min deflection angle to max deflection angle, whatever those angles are given your graphics.
     
    CovalenceSTU likes this.
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,893
    A sprite is a static asset like a 3d model, sound file, or image file(in fact it is an image file). The thing you want to rotate on the UI is called Image, which is an actual UI component that uses the sprite to draw itself. Image has a transform component.

    Edit: wow all three of us commented at once..
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    That was pretty classic.... poor OP is probably going "whoaaaaaaa!" like Tom Bombadil when Frodo runs up to him the first time...

    Well at least OP knows he's loved here!
     
    CovalenceSTU and PraetorBlue like this.
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,893
    I think what may be contributing OP's confusion is the fact that in the editor there is an option called:
    GameObject -> 2D Object -> Sprite, which in fact creates a GameObject with a SpriteRenderer component on it.

    This confused me a lot when I was trying to learn the relationship between 2D game elements and UI elements.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Agreed. Hey @CovalenceSTU , what @PraetorBlue means is when you drag a Sprite (the graphic) into a scene, the Editor automagically does a ton of complex things:

    - makes a new GameObject (all GameObjects have some kind of Transform on them)
    - adds a SpriteRenderer to it
    - fills out that SpriteRenderer's "sprite" property with your Sprite graphic

    All in a blink... and add to that, the colloquial term for a shape anywhere on the screen is often just "Sprite," which gets confusing because that's not the technical meaning in Unity, as Praetor and Antistone and I pointed out.
     
  8. CovalenceSTU

    CovalenceSTU

    Joined:
    Sep 10, 2018
    Posts:
    63
    Using SpriteRenderer instead of Sprite worked, thanks! I also used Mathf.Lerp (like you suggested).
     
    Kurt-Dekker likes this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Looking about a bit more, I don't think you need that setup() function to be a coroutine, unless you're looking ahead. It can just be renamed to Start() and go that way... unless there's something else about your setup I don't see from this view.

    Glad you're operational!
     
  10. CovalenceSTU

    CovalenceSTU

    Joined:
    Sep 10, 2018
    Posts:
    63
    I have a new problem related to rotating the needle - it rotates fine, but it spins around in circles, even past the Mathf.Lerp limits.

    Needle.transform.Rotate(0f, 0f, Mathf.Lerp(-225, 0, -carSpeed * 1.5f), Space.Self)


    Using Space.World causes it to rotate wildly on all axes, not just the z-axis. What can I do to stop this?
     
  11. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,893
    Transform.Rotate is an additive operation. It takes the rotation you give it, and adds to the object's existing rotation. Instead of using Transform.Rotate, try setting the rotation directly:

    Code (CSharp):
    1. Needle.transform.localRotation = Quaternion.Euler(0f, 0f, Mathf.Lerp(-225, 0, -carSpeed * 1.5f));
     
    Kurt-Dekker and CovalenceSTU like this.