1

I'm using unity 5.1.2 if that makes a difference.

I have a game object shield, that I want to move in a circle around a player. I have it working to a degree, the shield responds well to input but is not animated in that it just teleports to the new position instead of moving around in a circle in a smooth rotation. The game is 2D top down so working in the x/y plane only. Have tried to use lerp and slerp but not getting any joy

Would really appreciate your help to figure this one out!

Here's what I have so far:

public class ShieldMovement : MonoBehaviour {

    public Transform target; //player shield is attaced to

    float distance = 0.8f; // distance from player so it doesn't clip
    Vector3 direction = Vector3.up;


    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

        float angle = Mathf.Atan2 (Input.GetAxisRaw("rightH"), Input.GetAxisRaw("rightV"))* Mathf.Rad2Deg;

        if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
        {
            direction =  new Vector3(Input.GetAxis("rightH"),Input.GetAxis("rightV"), 0.0f ) ;
        }

        Ray ray = new Ray(target.position, direction);
        transform.position = ray.GetPoint(distance);

        if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f)
        {
            transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1);
        }
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Al Wyvern
  • 199
  • 1
  • 15
  • are you trying to get `transform.position` to move smoothly or `transform.rotation`? – Steven Mills Aug 31 '15 at 15:09
  • 1
    Something that may save you a bit of code is to parent the shield under an empty transform, then center and parent the empty transform under the player. That way, you don't need to figure out the rotation/position of the shield, just the rotation of its parent. (Just offering alternatives to your current approach.) – Serlite Aug 31 '15 at 15:28
  • @StevenMills transform.position. Essentially if the shield is in the bottom right, and i move the stick directly to top left, the shield disappears from bottom left and immediately appears in top right, instead of smoothly moving around in a circle until it reaches it's new point. – Al Wyvern Aug 31 '15 at 20:13

2 Answers2

0

Try this. With so many method calls to Input.GetAxis("...") you really want to just call it once in the beginning and cache it to a variable to speed things up. Also you don't really need to check if(Input.GetAxis("rightH") != 0f || Input.GetAxis("rightV") != 0f) twice, so i put everything into one of the checks. I added a multiplication by Time.smoothDeltaTime to hopefully smooth things out for you

float h = Input.GetAxis("rightH");
float v = Input.GetAxis("rightV");

float angle = Mathf.Atan2(h, v) * Mathf.Rad2Deg;

if(h != 0f || v != 0f)
{
    float step = Time.smoothDeltatime * speed;
    direction = Vector3.RotateTowards(transform.forward, new Vector2(h, v).normalized, step, 0.0F);
    Ray2D ray = new Ray2D(target.position, direction);
    transform.position = ray.GetPoint(distance);
    transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
}
maraaaaaaaa
  • 7,749
  • 2
  • 22
  • 37
  • Thanks for the tip on method calling, my code looks much better now! However adding Time.smoothDeltaTime did nothing for the changing angle and broke my rotation xD – Al Wyvern Aug 31 '15 at 20:15
  • The code works, but only as before, no smooth movement around the curve of the circle – Al Wyvern Aug 31 '15 at 20:25
  • can you try it now? i noticed the direction wasn't normalized, and `Quaternion` is now multiplied by the rotation – maraaaaaaaa Aug 31 '15 at 20:33
  • The shield still teleports to the new position, but now the shield is rotating on the spot as long as I hold the stick in the direction. The rotation in my code was fine as it made the shield face the right direction at any given angle, however it was the movement around the player that was the problem. – Al Wyvern Aug 31 '15 at 20:42
  • I think if I could find as way to Lerp the direction vector it would indirectly Lerp the transform.position through the Ray? Though I can't seem to get it to work – Al Wyvern Aug 31 '15 at 20:46
  • Yes, you want a `Lerp` updated. `RotateTowards(...)` is your `Lerp` in this case – maraaaaaaaa Aug 31 '15 at 20:48
0

After much searching and a bit of help I finally solved the problems, thanks guys :) Here's the solution I came up with

public class ShieldMovement : MonoBehaviour {

public Transform target; //player shield is attaced to

float distance = 0.8f; // distance from player so it doesn't clip
Vector3 direction = Vector3.up;
public float circSpeed = 0.1f; // Speed Shield moves around ship


// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {

    float rh = Input.GetAxisRaw("rightH");
    float rv = Input.GetAxisRaw("rightV");

    if(Mathf.Abs(rh) > 0.15f || Mathf.Abs(rv) > 0.15f)
    {
        Vector3 targetDir = new Vector3(rh, rv, 0.0f);
        direction  = Vector3.Slerp(transform.position-target.position, targetDir, circSpeed);

    }

    Ray ray = new Ray(target.position, direction); // cast ray in direction of point on circle shield is to go

    transform.position = ray.GetPoint(distance); //move shield to the ray as far as the radius

    float angleY = transform.position.y - target.position.y;
    float angleX = -(transform.position.x - target.position.x);

    float angle = Mathf.Atan2 (angleY, angleX) * Mathf.Rad2Deg-90; //Get angle

    if(Mathf.Abs(rh) > 0.15f || Mathf.Abs(rv) > 0.15f)
    {
        transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1); // keep shield facing outwards in respect to player, will need revisiting on animating shield properly
    }


}

}

Al Wyvern
  • 199
  • 1
  • 15