As the title describes, I am trying to make my projectile go into the direction the player is facing. Currently the projectile only shoots towards the right, even if the player is facing left.
*** I am new to C# (learning)** *** I am following tutorials to reach the point I am at currently**
I have tried various methods but everything I have tried failed so far. The community of StackOverflow is my last hope.
There are (what I believe) three different scripts that are important regarding this mechanic. It is a player attack mechanic that shoots a projectile.
The three different scripts are called:
- Projectile.cs
- PlayerAttack.cs
- PlayerMovement.cs
Code Projectile:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
[SerializeField] private float speed;
private float direction;
private bool hit;
private Animator anim;
private BoxCollider2D boxCollider;
private void Awake()
{
anim = GetComponent<Animator>();
boxCollider = GetComponent<BoxCollider2D>();
}
private void Update()
{
if(hit) return;
float movementSpeed = speed * Time.deltaTime * direction;
transform.Translate(movementSpeed, 0, 0);
}
private void OnTriggerEnter2D(Collider2D collision)
{
hit = true;
boxCollider.enabled = false;
anim.SetTrigger("explode");
}
public void SetDirection(float _direction)
{
direction = _direction;
gameObject.SetActive(true);
hit = false;
boxCollider.enabled = true;
float localScaleX = transform.localScale.x;
if(Mathf.Sign(localScaleX) != _direction)
localScaleX = -localScaleX;
transform.localScale = new Vector3(localScaleX, transform.localScale.y, transform.localScale.z);
}
private void Deactivate()
{
gameObject.SetActive(false);
}
}
Code PlayerAttack:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttack : MonoBehaviour
{
[SerializeField] private float attackCooldown;
[SerializeField] private Transform firePoint;
[SerializeField] private GameObject[] ghostballs;
private Animator anim;
private PlayerMovement playerMovement;
private float cooldownTimer = Mathf.Infinity;
private void Awake()
{
anim = GetComponent<Animator>();
playerMovement = GetComponent<PlayerMovement>();
}
private void Update()
{
if (Input.GetMouseButton(0) && cooldownTimer > attackCooldown && playerMovement.canAttack())
Attack();
cooldownTimer += Time.deltaTime;
}
private void Attack()
{
anim.SetTrigger("attack");
cooldownTimer = 0;
ghostballs[FindGhostball()].transform.position = firePoint.position;
ghostballs[FindGhostball()].GetComponent<Projectile>().SetDirection(Mathf.Sign(transform.localScale.x));
}
private int FindGhostball()
{
for (int i = 0; i < ghostballs.Length; i++)
{
if (!ghostballs[i].activeInHierarchy)
return i;
}
return 0;
}
}
Code PlayerMovement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{ //variables
private Rigidbody2D rb;
private BoxCollider2D coll;
private SpriteRenderer sprite;
private Animator anim;
[SerializeField] private LayerMask jumpableGround;
private float dirX = 0f;
[SerializeField] private float moveSpeed = 7f;
[SerializeField] private float jumpForce = 14f;
private enum MovementState { idle, running, jumping, falling }
[SerializeField] private AudioSource jumpSoundEffect;
// Start is called before the first frame update
private void Start()
{
rb = GetComponent<Rigidbody2D>();
coll = GetComponent<BoxCollider2D>();
sprite = GetComponent<SpriteRenderer>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
private void Update()
{
dirX = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector2(dirX * moveSpeed, rb.velocity.y);
if (Input.GetButtonDown("Jump") && IsGrounded())
{
jumpSoundEffect.Play();
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
AnimState();
}
private void AnimState()
{
MovementState state;
if (dirX > 0f)
{
state = MovementState.running;
sprite.flipX = false;
}
else if (dirX < 0f)
{
state = MovementState.running;
sprite.flipX = true;
}
else
{
state = MovementState.idle;
}
if (rb.velocity.y > .1f)
{
state = MovementState.jumping;
}
else if (rb.velocity.y < -.1f)
{
state = MovementState.falling;
}
anim.SetInteger("state", (int)state);
}
private bool IsGrounded()
{
return Physics2D.BoxCast(coll.bounds.center, coll.bounds.size, 0f, Vector2.down, .1f, jumpableGround);
}
public bool canAttack()
{
return IsGrounded();
}
}
I appreciate your time investment into resolving my issue. I hope I will find a solution soon since this is a big hurdle for me currently and stops me from progressing.
I have tried messing around with the SetDirection method as I believe there lays the problem but I am uncertain. As I stated in the beginning, I am totally new to C# and Unity.
public void SetDirection(float _direction)
{
lifetime = 0;
direction = _direction;
gameObject.SetActive(true);
hit = false;
boxCollider.enabled = true;
float localScaleX = transform.localScale.x;
if (Mathf.Sign(localScaleX) != _direction)
{
localScaleX = -localScaleX;
speed = -speed; // Flip the sign of the speed if facing opposite direction
}
transform.localScale = new Vector3(localScaleX, transform.localScale.y, transform.localScale.z);
}