Hello,
I’ve been learning unity and programming for that matter for the past week and yesterday i have encountered 2 problems that i just couldn’t solve on my own or with the help of available materials on the internet so, here i am.
-
basically, im trying to force movement of mouse cursor whenever i shoot to imitate recoil of the gun in a 2D, top-down shooter game.
the movement im trying to get has to be different for each gun, so probably a customizable “recoil” value. -
Another problem - i want to push enemies a little bit back whenever they are being hit by a projectile with speed higher than X. I’ve tried doing that with RigidBody2D but it didnt work Probably has to do something with projectile code(last one here)
My current example codes:
Enemy code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemy : MonoBehaviour
{
public float health;
public void TakeDamage(float damage) {
health -= damage;
if (health <=0)
{
Destroy(gameObject);
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Player code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MilkShake;
public class player : MonoBehaviour
{
[Header("Movement speed")]
public int movementSpeed;
[Header("Movement speed while shooting")]
public int movementSpeed2;
[Header("Movement speed while zoomed in")]
public int movementSpeed3;
public int rotationSpeed;
private Rigidbody2D rb;
private Vector2 moveAmount;
private Animator anim;
private float _horizontalInput = 0;
private float _verticalInput = 0;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
Vector2 moveInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
// movement speed while shooting
if (Input.GetKey(KeyCode.Mouse0)){
rb.AddForce(moveInput.normalized * movementSpeed2);
}
//movement speed while zoomed in
if (Input.GetKey(KeyCode.Mouse1)){
rb.AddForce(moveInput.normalized * movementSpeed3);
}
//movement speed
else{
rb.AddForce(moveInput.normalized * movementSpeed);
}
//animation
if (moveInput != Vector2.zero) {
anim.SetBool("isWalking", true);
}
else {
anim.SetBool("isWalking", false);
}
}
private void FixedUpdate()
{
rb.MovePosition(rb.position + moveAmount * Time.fixedDeltaTime);
}
}
Gun code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using MilkShake;
public class kar98k : MonoBehaviour
{
[Header("Game objects")]
public GameObject projectile;
//fire from barrel
public GameObject muzzleflash;
public Transform shotPoint;
[Header("Rate of fire")]
// rate of fire of a gun
public float rateOfFire;
//timeBetweenShooting = shotTime, timeBetweenShots = rateoffire;
private float shotTime;
public float timeBetweenShooting;
[Header("Spread settings")]
public float spread;
public float spreadmovews;
public float spreadmovead;
[Header("Reload settings")]
public float reloadTime;
[Header("Is full auto?")]
public bool allowButtonHold;
[Header("Ammo settings")]
public int bulletsLeft, bulletsShot;
public int magazineSize, magazineSizefull, bulletsPerTap;
[Header("Other settings")]
public float range;
public TextMeshProUGUI text;
bool shooting, readyToShoot, reloading;
private float spreadx;
private float spreadm;
//animation
public Animator animator;
//shaker
public Shaker CamShake;
public ShakePreset Kar98kRecoil;
private void Awake()
{
readyToShoot = true;
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float spreadx = Random.Range(-spread, spread);
//rozrzut w ruchu
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D))
spreadm = Random.Range(-spread, spread) * spreadmovews;
else spreadm = spreadx;
// weapon
Vector2 direction = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.AngleAxis(angle - 90, Vector3.forward);
transform.rotation = rotation;
MyInput();
//angle, spread
Quaternion bulletSpread = Quaternion.Euler(new Vector3(0, 0, spreadm));
if (Time.time >= shotTime) {
if (readyToShoot && shooting && !reloading && magazineSize > 0){
bulletsShot = bulletsPerTap;
Shoot();
Instantiate(projectile, shotPoint.position, rotation * bulletSpread);
Instantiate(muzzleflash, shotPoint.position, transform.rotation);
shotTime = Time.time + rateOfFire;
}
}
//}
}
private void MyInput ()
{
//shooting full auto or not
if (allowButtonHold) shooting = Input.GetKey(KeyCode.Mouse0);
else shooting = Input.GetKeyDown(KeyCode.Mouse0);
if (Input.GetKeyDown(KeyCode.R) && bulletsLeft > magazineSize && !reloading){
Reload();
}
}
//----------------------------------- S H O O T I N G -----------------------------------------
public void Shoot ()
{
//sound
AudioSource audio = gameObject.AddComponent<AudioSource>();
audio.PlayOneShot((AudioClip)Resources.Load("kar98ks"));
//camera shake, recoil
CamShake.Shake(Kar98kRecoil);
readyToShoot = false;
magazineSize--;
bulletsShot--;
Invoke("ResetShot", timeBetweenShooting);
if(magazineSize > 0 && bulletsShot > 0)
{
Invoke("Shoot", rateOfFire);
//animation
animator.SetTrigger("attack1");
}
//auto reload
if(magazineSize == 0 && bulletsLeft > 0){
Reload();
}
}
private void ResetShot()
{
readyToShoot = true;
}
private void Reload()
{
reloading = true;
Invoke("ReloadFinished", reloadTime);
}
private void ReloadFinished()
{
magazineSize = magazineSizefull;
bulletsLeft = bulletsLeft - magazineSizefull;
reloading = false;
}
}
Projectile code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class N9mm : MonoBehaviour
{
[Header("Speed settings")]
// speed of the bullet
public float SpeedLossFactor; //has to be below 1
public float SpeedIncreaseFactor;
public float SpeedMax;
private float speedDamageFactor; //speed incease by each update
public float speed = 50;
[Header("Damage Settings")]
public float damageMin;
public float damageMax;
private float damage;
private int damageAfterPen;
[Header("Other Settings")]
public float lifeTime = 5;
[Header("Is armor piercing?")]
public float arp;
// lifetime of a bullet
//sound
// Start is called before the first frame update
void Start()
{
//bullet dissapears
Destroy(gameObject, lifeTime);
}
// Update is called once per frame
void Update()
{
if(speed < SpeedMax && speed > 40){
speed = speed + SpeedIncreaseFactor;
}
speedDamageFactor = speed - 50;
transform.Translate(Vector2.up * speed * Time.deltaTime);
}
void DestroyProjectile() {
Destroy(gameObject);
}
private void OnTriggerEnter2D(Collider2D collision){
float damage = Random.Range(damageMin, damageMax) + speedDamageFactor;
if (collision.tag == "enemy" && speed > 60 && arp == 0)
{
// if speed is above 60 and armor piercing = 0, the object thats been hit is pushed.
collision.GetComponent<enemy>().TakeDamage(damage);
speed = speed * SpeedLossFactor;
} if (collision.tag == "enemy" && speed > 60 && arp == 1) {
// if speed is above 60 and armor piercing = 1, the bullet goes through the target without pushing him
collision.GetComponent<enemy>().TakeDamage(damage);
speed = speed * SpeedLossFactor;
}
if (collision.tag == "enemy" && speed <= 60) {
// if bullet speed is below 60 the target wont be pushed back.
collision.GetComponent<enemy>().TakeDamage(damage);
speed = speed * SpeedLossFactor;
}
if(collision.tag == "objects"){
collision.GetComponent<objects>().TakeDamage(damage);
speed = speed * SpeedLossFactor;
}
if(collision.tag == "ally"){
speed = speed * SpeedLossFactor;
}
if (speed <= 25){
DestroyProjectile();
}
}
}
any help would be appreciated.