0
\$\begingroup\$

I am making a game in unity 3d. It is a 2.5d game which mean it is in isometric. The game is quite simple. Player drags mouse and a trajectory will be shown just like in angry bird and when player release the mouse the ball will move to the direction. However I am having issue here that once mouse is released the ball moves in exact opposite direction. I am not able to understand what the real issue is. My code is as follows:

For Ball:

public class BallScript : MonoBehaviour

{
    public Rigidbody2D rbg;
    public CircleCollider2D col;

    public Vector3 BallPos{
        get {return transform.position;}
    }


    void Awake(){
        rbg = GetComponent<Rigidbody2D>();
        col = GetComponent<CircleCollider2D>();
    }

    public void PushBall(Vector2 force){
        rbg.AddForce(force,ForceMode2D.Impulse);
    }

    //to enable rigidbody so we can use projectile again
    public void ActivateRb(){
        rbg.isKinematic = false;
    }

    public void DeActivateRb(){
        rbg.velocity = Vector3.zero;
        rbg.angularVelocity = 0f;
        rbg.isKinematic = true;
    }
}

The code for my game manager is as follows:

public class Trajectory : MonoBehaviour
{
    [SerializeField] int dotsNumbers;
    [SerializeField] GameObject dotsParent;
    
    [SerializeField] GameObject DotsPrefab;
    [SerializeField] float dotSpacing;
    Vector2 pos;
    float timeStamp;
    Transform[] dotsList;

    void Start(){
        //hide trajectory in the start
        Hide();

        PrepareDots();
    }

    void PrepareDots(){
        dotsList = new Transform[dotsNumbers];
        for(int i=0;i<dotsNumbers;i++){
            dotsList[i] = Instantiate(DotsPrefab,null).transform;
            dotsList[i].parent = dotsParent.transform;
        }
    }
    public void UpdateDots(Vector3 ballPos,Vector2 forceApplied){
        timeStamp = dotSpacing;
        for(int i=0;i<dotsNumbers;i++){
            pos.x = (ballPos.x + forceApplied.x * timeStamp);
            pos.y = (ballPos.y + forceApplied.y * timeStamp)-(Physics2D.gravity.magnitude * timeStamp * timeStamp)/2f;
            dotsList[i].position = pos;
            timeStamp += dotSpacing;
        }
    }


    public void Show(){
        dotsParent.SetActive(true);
    }
    public void Hide(){
        dotsParent.SetActive(false);
    }
}

Here is the code for gamemanager

// using singleton pattern 
Camera cam;
public BallScript ball;
public Trajectory trajectory;
public static GameManagerScript Instance;
void Awake(){
    if(Instance==null){
        Instance = this;
    }
}


[SerializeField] float pushForce = 4f;
bool isDragging = false;

Vector2 startPoint;
Vector2 endPoint;
Vector2 direction;
 Vector2 force;
float distance;


void Start(){
    cam = Camera.main;
    ball.DeActivateRb();
}

void Update(){
    if(Input.GetMouseButtonDown(0)){
        isDragging = true;
        OnDragStart();
    }
    if(Input.GetMouseButtonUp(0)){
        isDragging = false;
        OnDragEnd();
    }
    if(isDragging){
        OnDrag();
    }
}

void OnDragStart(){
    ball.DeActivateRb();
    startPoint = cam.ScreenToWorldPoint(Input.mousePosition);
    trajectory.Show();
}

void OnDrag(){
    endPoint = cam.ScreenToWorldPoint(Input.mousePosition);
    distance = Vector2.Distance(startPoint,endPoint);
    direction = (endPoint-startPoint).normalized;
    force = direction* distance * pushForce;

    trajectory.UpdateDots(ball.BallPos,force);
    
}

void OnDragEnd(){
    ball.ActivateRb();
    ball.PushBall(force);
    trajectory.Hide();
}

The ball moves in exact opposite direction where I wish to send it by dragging. Is it because of the isometric issue or I am missing something?P.S: have applied negative force as well as in case and have also made change in direction formula

rbg.AddForce(-force,ForceMode2D.Impulse);
direction = (startPoint-endPoint).normalized;
\$\endgroup\$
4
  • \$\begingroup\$ Did you change the direction and the force formulas both at once? If so, then you just made it the same again as if you didn't change them. Leave the force formula at 1st variant ( rbg.AddForce(force,ForceMode2D.Impulse); ) and then change the direction formula. To get the direction from startPoint to endPoint you di this endPoint - startPoint. To get the direction from endPoint to startPoint: startPoint - endPoint. It's a bit counterintuitive, but that's how vector math works. \$\endgroup\$
    – vexaiv
    Commented May 24, 2021 at 12:19
  • \$\begingroup\$ @Ermiq nope I changed once each one of it and then changed it again together. Tried it both ways. No difference. \$\endgroup\$ Commented May 24, 2021 at 12:37
  • \$\begingroup\$ Does the trajectory show correctly, or is it also backwards? \$\endgroup\$
    – Kevin
    Commented May 26, 2021 at 4:59
  • \$\begingroup\$ @Kevin The trajectory is working perfectly fine as intended! \$\endgroup\$ Commented May 27, 2021 at 8:30

1 Answer 1

1
\$\begingroup\$

Some suggestions:

When you call ScreenToWorldPoint(), you generally should not pass in the mouse position directly. You need to set the z-position first. For example,

Vector3 mousePosition = Input.mousePosition;
mousePosition.z = cam.nearClipPlane;
endPoint = cam.ScreenToWorldPoint(mousePosition);

This part of your OnDrag() is pointlessly complicated:

distance = Vector2.Distance(startPoint,endPoint);
direction = (endPoint-startPoint).normalized;
force = direction* distance * pushForce;

Let's analyze what you're doing here:

  1. Calculate the scalar distance.
  2. Get the Vector3 from startPoint to endPoint
  3. Normalize the Vector3 from step 2 to get a direction.
  4. Multiply the distance from step 1 and direction from step 3 to get the Vector3 from startPoint to endPoint.

Hold on a minute - the value you end up with in step 4 is the same value you got in step 2. You don't need the other steps! This can be simplified to

force = (endPoint - startPoint) * pushForce;
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .