/* Arrow.cs */ | |
using UnityEngine; | |
public class Arrow : MonoBehaviour | |
{ | |
[SerializeField] | |
private float damage; | |
[SerializeField] | |
private float torque; | |
[SerializeField] | |
private Rigidbody rigidbody; | |
private string enemyTag; | |
private bool didHit; | |
public void SetEnemyTag(string enemyTag) | |
{ | |
this.enemyTag = enemyTag; | |
} | |
public void Fly(Vector3 force) | |
{ | |
rigidbody.isKinematic = false; | |
rigidbody.AddForce(force, ForceMode.Impulse); | |
rigidbody.AddTorque(transform.right * torque); | |
transform.SetParent(null); | |
} | |
void OnTriggerEnter(Collider collider) | |
{ | |
if (didHit) return; | |
didHit = true; | |
if (collider.CompareTag(enemyTag)) | |
{ | |
var health = collider.GetComponent<HealthController>(); | |
health.ApplyDamage(damage); | |
} | |
rigidbody.velocity = Vector3.zero; | |
rigidbody.angularVelocity = Vector3.zero; | |
rigidbody.isKinematic = true; | |
transform.SetParent(collider.transform); | |
} | |
} | |
/* Weapon.cs */ | |
using System.Collections; | |
using UnityEngine; | |
public class Weapon : MonoBehaviour | |
{ | |
[SerializeField] | |
private float reloadTime; | |
[SerializeField] | |
private Arrow arrowPrefab; | |
[SerializeField] | |
private Transform spawnPoint; | |
private Arrow currentArrow; | |
private string enemyTag; | |
private bool isReloading; | |
public void SetEnemyTag(string enemyTag) | |
{ | |
this.enemyTag = enemyTag; | |
} | |
public void Reload() | |
{ | |
if (isReloading || currentArrow != null) return; | |
isReloading = true; | |
StartCoroutine(ReloadAfterTime()); | |
} | |
private IEnumerator ReloadAfterTime() | |
{ | |
yield return new WaitForSeconds(reloadTime); | |
currentArrow = Instantiate(arrowPrefab, spawnPoint); | |
currentArrow.transform.localPosition = Vector3.zero; | |
currentArrow.SetEnemyTag(enemyTag); | |
isReloading = false; | |
} | |
public void Fire(float firePower) | |
{ | |
if (isReloading || currentArrow == null) return; | |
var force = spawnPoint.TransformDirection(Vector3.forward * firePower); | |
currentArrow.Fly(force); | |
currentArrow = null; | |
Reload(); | |
} | |
public bool IsReady() | |
{ | |
return (!isReloading && currentArrow != null); | |
} | |
} | |
/* WeaponController.cs */ | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class WeaponController : MonoBehaviour | |
{ | |
[SerializeField] | |
private Text firePowerText; | |
[SerializeField] | |
private Weapon weapon; | |
[SerializeField] | |
private string enemyTag; | |
[SerializeField] | |
private float maxFirePower; | |
[SerializeField] | |
private float firePowerSpeed; | |
private float firePower; | |
[SerializeField] | |
private float rotateSpeed; | |
[SerializeField] | |
private float minRotation; | |
[SerializeField] | |
private float maxRotation; | |
private float mouseY; | |
private bool fire; | |
void Start() | |
{ | |
weapon.SetEnemyTag(enemyTag); | |
weapon.Reload(); | |
Cursor.visible = false; | |
Cursor.lockState = CursorLockMode.Locked; | |
} | |
void Update() | |
{ | |
mouseY -= Input.GetAxis("Mouse Y") * rotateSpeed; | |
mouseY = Mathf.Clamp(mouseY, minRotation, maxRotation); | |
weapon.transform.localRotation = Quaternion.Euler(mouseY, weapon.transform.localEulerAngles.y, weapon.transform.localEulerAngles.z); | |
if (Input.GetMouseButtonDown(0)) | |
{ | |
fire = true; | |
} | |
if (fire && firePower < maxFirePower) | |
{ | |
firePower += Time.deltaTime * firePowerSpeed; | |
} | |
if (fire && Input.GetMouseButtonUp(0)) | |
{ | |
weapon.Fire(firePower); | |
firePower = 0; | |
fire = false; | |
} | |
if (fire) | |
{ | |
firePowerText.text = firePower.ToString(); | |
} | |
} | |
} | |
/* HealthController.cs */ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class HealthController : MonoBehaviour | |
{ | |
[SerializeField] | |
private float maxHealth; | |
private float currentHealth; | |
[SerializeField] | |
private float respawnTime; | |
[SerializeField] | |
private GameObject healthPanel; | |
[SerializeField] | |
private Text healthText; | |
[SerializeField] | |
private RectTransform healthBar; | |
private float healthBarStartWidth; | |
private MeshRenderer meshRenderer; | |
private bool isDead; | |
void Start() | |
{ | |
meshRenderer = GetComponent<MeshRenderer>(); | |
currentHealth = maxHealth; | |
healthBarStartWidth = healthBar.sizeDelta.x; | |
UpdateUI(); | |
} | |
public void ApplyDamage(float damage) | |
{ | |
if (isDead) return; | |
currentHealth -= damage; | |
if (currentHealth <= 0) | |
{ | |
currentHealth = 0; | |
isDead = true; | |
meshRenderer.enabled = false; | |
healthPanel.SetActive(false); | |
StartCoroutine(RespawnAfterTime()); | |
} | |
UpdateUI(); | |
} | |
private IEnumerator RespawnAfterTime() | |
{ | |
yield return new WaitForSeconds(respawnTime); | |
ResetHealth(); | |
} | |
private void ResetHealth() | |
{ | |
currentHealth = maxHealth; | |
isDead = false; | |
meshRenderer.enabled = true; | |
healthPanel.SetActive(true); | |
UpdateUI(); | |
} | |
private void UpdateUI() | |
{ | |
float percentOutOf = (currentHealth / maxHealth) * 100; | |
float newWidth = (percentOutOf / 100) * healthBarStartWidth; | |
healthBar.sizeDelta = new Vector2(newWidth, healthBar.sizeDelta.y); | |
healthText.text = currentHealth + "/" + maxHealth; | |
} | |
} | |
/* Movement.cs */ | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class Movement : MonoBehaviour | |
{ | |
[SerializeField] | |
private float movementSpeed = 10; | |
private new Rigidbody rigidbody; | |
void Start () | |
{ | |
rigidbody = GetComponent<Rigidbody>(); | |
} | |
void Update() | |
{ | |
float h = Input.GetAxis("Horizontal"); | |
float v = Input.GetAxis("Vertical"); | |
Vector3 velocity = new Vector3(h, 0, v); | |
velocity = transform.TransformDirection(velocity); | |
velocity *= movementSpeed; | |
velocity -= rigidbody.velocity; | |
rigidbody.AddForce(velocity); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment