So I have a turret prefab, of which the turning part I want to follow the player and shoot at him repeatedly.
Now, through following multiple tutorials and writing some of my own code, I was able to get it to;
- follow the player on the Y axis smoothly, if he enters it’s range
- instatiate projectiles
However! The turret faces the player on the X axis only slightly, going down only by a few degrees (they seem to “hover” around 0-1.123 etc.) and It was facing away from the player originally, so I have changed the follow on X axis to be on -x, so now it turns towards the player, but the facing issue remains.
Also, the instantiated projectiles drop to the ground, instead of inheriting the give velocity. I had used the same script that worked for my player’s weapon, which still works.
This is the turret’s aiming script + it’s firing script in one. The shell only has a rigidbody, an explode-on-contact script and a capsule collider, which is not a trigger.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SentryAI : MonoBehaviour
{
public Transform targetingPlayer;
public GameObject sentryShell;
public Transform sentryMuzzle; //empty gameObject at the end of a barrel
[Header ("Attributes")]
public float range = 15f;
public float sentryFireRate = 1f;
private float fireCooldown = 0f;
public float detterentForce = 80; //force value, that's supposed to be given to the shell
[Header ("Unity Setup Fields")]
public Transform partToRotate;
public float sentrySpeed = 5f;
public string playerTag = "Player";
void Start()
{
InvokeRepeating("UpdateTarget", 0f, 2f);
}
void UpdateTarget()
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag(playerTag); //Player has an empty gameObject in the lower-mid of his tank with this tag
float shortestDistance = Mathf.Infinity;
GameObject nearestEnemy = null;
foreach (GameObject enemy in enemies)
{
float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
if (distanceToEnemy < shortestDistance)
{
shortestDistance = distanceToEnemy;
nearestEnemy = enemy;
}
}
// Target nearest enemy - may be unnecessary
if (nearestEnemy != null && shortestDistance <= range)
{
targetingPlayer = nearestEnemy.transform;
}
else
{
targetingPlayer = null;
}
}
void Update()
{
if (targetingPlayer == null)
return;
// This is the lock-on
Vector3 dir = targetingPlayer.position - transform.position;
Quaternion lookRotation = Quaternion.LookRotation(dir);
Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * sentrySpeed).eulerAngles;
partToRotate.rotation = Quaternion.Euler(rotation.x, rotation.y, 0f); //The rotation X here is supposed to do the same thing as Y, which works, but it only angles by under 2 degrees max
if(fireCooldown <= 0)
{
Engage();
fireCooldown = 1f / sentryFireRate;
}
fireCooldown -= Time.deltaTime;
}
void Engage()
{
GameObject finstabilized = (GameObject)Instantiate(sentryShell, sentryMuzzle.position, sentryMuzzle.rotation);
Rigidbody rb = sentryShell.GetComponent<Rigidbody>();
rb.AddForce(transform.forward * detterentForce, ForceMode.VelocityChange); //this is supposed to add force to the shells - currently they drop to the ground
}
private void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere(transform.position, range);
}
}
I am running out of time to finish this project - otherwise I’d try to figure it out on my own. Next time, I’ll try to make something even simpler, because it seems I had though-out a too difficult of a project to make and I feel bad about asking so many questions.