Hi, Before anything else, sorry if this thread is in the wrong place, I will gladly move it if it is the case. So, I'm currently developing a 2D platformer (my first one, hurra) and I'm having a bit of trouble with the last part of my programming. The character is supposed to be able to shoot in the direction of the cursor (which follows the movements of the mouse), and then be moved in the other direction (as a standard recoil). So i did this: Code (CSharp): Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y); Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector2 direction = target - PointDeTirPosition; Vector2 Recoil = new Vector2(PointDeTir.position.x - Curseur.position.x, PointDeTir.position.y - Curseur.position.y); Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; difference.Normalize(); direction.Normalize(); Recoil.Normalize(); float RotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg; GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.Euler(0f, 0f, RotZ)); clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1; GetComponent<Rigidbody2D>().AddForce(Recoil * RecoilStrength1, ForceMode2D.Impulse); It works pretty well, except for the X axis: there, the movement is instaneous and almost non-existent, whereas the Y axis works perfectly. Any idea where it comes from ? Thank you a lot to those who will give it a try
Ok your code looks a bit complicated but I have 2 questions. Are you using transform.right and why are you normalizing everything.
Hi, thank you for your time !Yes the code is quite messed up, I had problems all along the way so I stitched up some parts... I am not using transform.right, though I have tried Addforce, Rigidbody velocity and transform.translate. I like Addforce the most, because it's the smoothest and delivers a short burst of movement (such as one would expect from a shooting weapon), but as far as I went, X axis doesn't receive more than one tenth of the force applied to Y axis. I normalized vector because I want the force applied to be normalized: before I did, the force applied to projectiles and to player afetr a shot was proportionnal to the distance between the player and the cursor (which was definitely not what i wanted), so this shouldn't be the problem.
transform.right is the direction and can be used instead of rotation over mathf.atan. as example: Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; clone.transform.right = difference; (you can use transform.right, transform.up, - transform.right, -transform.up) what is PointDeTir ? Can it be that rigidbody from the projectile is locked on x ? I think your code should work, I have tested (with PointDeTir as gameobject.transform) and the projectile are flying in all directions. Code (CSharp): public Transform PointDeTir; public GameObject Projectile1; public float ProjectileSpeed1; void Update() { if (Input.GetMouseButtonDown(0)) { Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y); Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector2 direction = target - PointDeTirPosition; Vector3 difference = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position; direction.Normalize(); float RotZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg; GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.Euler(0f, 0f, RotZ)); clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1; } } }
So I just tried this, and this only made the character rotate in the most hilarious way, I fail to understand how this could be the way And PointDeTir is french, it represents the position of an empty object where my particles and projectiles come from (tip of the weapon)
with transform.right in my example it whould be like: Code (CSharp): void Update() { if (Input.GetMouseButtonDown(0)) { Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y); Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector2 direction = target - PointDeTirPosition; direction.Normalize(); GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.identity); clone.transform.right = direction; clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1; } } you can use it as local vector: clone.GetComponent<Rigidbody2D>().velocity = clone.transform.right * ProjectileSpeed1;
I must have explained my problem poorly: the projectiles are all OK, the issue is in the recoil movement: the addforce I'm using on the character after a shot doesn't impact the X axis, and therefore makes the player skyrocket to the moon, while not moving more than 5 inches on the sides
It's ok, thanks to help me anyways ! Curseur is the gamebject following the mouse psoition, towards which the character is shooting
maybe you can just use opposite to shooting direction ? GetComponent<Rigidbody2D>().AddForce(- direction * RecoilStrength1, ForceMode2D.Impulse);
Well it's actually the same thing, given that Curseur is technically the target ! (I know, my code is stitched up like crap :^) ) I have tried it anyways, and the result is precisely the same, so I'm beggining to suspect that this a problem with Addforce and the X axis that i'm not seeing... I have searched on the net and haven't found a way yet: my rigidbody is dynamic, simulated, without constraints, mass gravity and drag are standard, animator doesn't have root motion applied...
just for test, will this move the object on x ? GetComponent<Rigidbody2D>().velocity = - direction * RecoilStrength1; I think your moving script can overwright the x-force
then do you move the player with velocity too ? I think you should disable moving at the shooting time (or use force for moving). Velocity change the moving vector directly, it is good for precise moving but ignoring the forces.
I do move him with velocity. I tried deleting Code (CSharp): moveY = Input.GetAxis("Vertical"); moveX = Input.GetAxis("Horizontal"); from my total code, but that didn't work
Oh yeah, totally works then ! So all I have to do is deactivate movement's velocity when the character is about to shoot, right ?
as example, I am sure it will not work good Code (CSharp): public Transform PointDeTir; public GameObject Projectile1; public float ProjectileSpeed1, RecoilStrength1, delay, speed; bool isShooting, canBePushed; Vector2 direction; Rigidbody2D rb; float x, y; void Start () { rb = GetComponent<Rigidbody2D>(); } void Update() { x = Input.GetAxis("Horizontal"); y = Input.GetAxis("Vertical"); if (Input.GetMouseButtonDown(0)) { Vector2 PointDeTirPosition = new Vector2(PointDeTir.position.x, PointDeTir.position.y); Vector2 target = Camera.main.ScreenToWorldPoint(Input.mousePosition); direction = target - PointDeTirPosition; direction.Normalize(); GameObject clone = (GameObject)Instantiate(Projectile1, PointDeTirPosition, Quaternion.identity); clone.transform.right = direction; clone.GetComponent<Rigidbody2D>().velocity = direction * ProjectileSpeed1; isShooting = true; canBePushed = true; StartCoroutine("MovingDelay"); } } void FixedUpdate () { if (!isShooting) { rb.velocity = new Vector2(x, y) * speed; } else if (canBePushed) { canBePushed = false; rb.velocity = Vector2.zero; rb.AddForce(-direction * RecoilStrength1, ForceMode2D.Impulse); } } IEnumerator MovingDelay () { yield return new WaitForSeconds(delay); isShooting = false; } } or as said, you can just move the player with force instead of velocity
Welp, this works top notch, thank you so much pal. here is the part of the code that I changed : Code (CSharp): Vector2 Recul = new Vector3(transform.position.x - Curseur.position.x, transform.position.y - Curseur.position.y); Recul.Normalize(); float elapsedTime = 0f; IsPushed = true; while (elapsedTime < duration) { gameObject.GetComponent<Rigidbody2D>().AddForce(Recul * RecoilStrength1); elapsedTime += Time.deltaTime; yield return null; } yield return new WaitForSeconds(1 / 10); CurrentEnergy = CurrentEnergy - EnergyCost1; UpdateHealthBar(); IsPushed = false; The only problem is that the movement ends up brutally by going down, and without any "floating" in the air (if you have any clue on how I could improve that :^) ), but I can definitely works with that ! Thank you a lot mate !
OK so I changed a few things so that the IsPushed boolean runs when the movement is being done, and this is rock solid ! Thank you a lot, and have a good day !