Skip to content

Instantly share code, notes, and snippets.

@gengen1988
Created April 22, 2021 16:07
Show Gist options
  • Save gengen1988/bc95661693dafc2d3bae486b86ef323a to your computer and use it in GitHub Desktop.
Save gengen1988/bc95661693dafc2d3bae486b86ef323a to your computer and use it in GitHub Desktop.
turret tutorial scripts
using UnityEngine;
public class Gun : MonoBehaviour
{
public GameObject shotPrefab;
public Transform[] gunPoints;
public float fireRate;
bool firing;
float fireTimer;
int gunPointIndex;
void Update()
{
if (firing)
{
while (fireTimer >= 1 / fireRate)
{
SpawnShot();
fireTimer -= 1 / fireRate;
}
fireTimer += Time.deltaTime;
firing = false;
}
else
{
if (fireTimer < 1 / fireRate)
{
fireTimer += Time.deltaTime;
}
else
{
fireTimer = 1 / fireRate;
}
}
}
void SpawnShot()
{
var gunPoint = gunPoints[gunPointIndex++];
Instantiate(shotPrefab, gunPoint.position, gunPoint.rotation);
gunPointIndex %= gunPoints.Length;
}
public void Fire()
{
firing = true;
}
}
using UnityEditor;
using UnityEngine;
public class MountPoint : MonoBehaviour
{
[Range(0, 360f)]
public float angleLimit = 90f;
[Range(0, 360f)]
public float aimTolerance = 1f;
public float turnSpeed = 90f;
Transform turret;
void OnDrawGizmos()
{
#if UNITY_EDITOR
var range = 20f;
var hardpoint = transform;
var from = Quaternion.AngleAxis(-angleLimit / 2, hardpoint.up) * hardpoint.forward;
Handles.color = new Color(0, 1, 0, .2f);
Handles.DrawSolidArc(hardpoint.position, hardpoint.up, from, angleLimit, range);
#endif
}
void Awake()
{
turret = transform.GetChild(0);
}
public bool Aim(Vector3 targetPoint)
{
return Aim(targetPoint, out _);
}
public bool Aim(Vector3 targetPoint, out bool reachAngleLimit)
{
reachAngleLimit = default;
var hardpoint = transform;
var los = targetPoint - hardpoint.position;
var halfAngle = angleLimit / 2;
var losOnPlane = Vector3.ProjectOnPlane(los, hardpoint.up);
var deltaAngle = Vector3.SignedAngle(hardpoint.forward, losOnPlane, hardpoint.up);
if (Mathf.Abs(deltaAngle) > halfAngle)
{
reachAngleLimit = true;
losOnPlane = hardpoint.rotation * Quaternion.Euler(0, Mathf.Clamp(deltaAngle, -halfAngle, halfAngle), 0) * Vector3.forward;
}
var targetRotation = Quaternion.LookRotation(losOnPlane, hardpoint.up);
var aimed = !reachAngleLimit && Quaternion.Angle(turret.rotation, targetRotation) < aimTolerance;
turret.rotation = Quaternion.RotateTowards(turret.rotation, targetRotation, turnSpeed * Time.deltaTime);
return aimed;
}
}
using UnityEngine;
public class Shot : MonoBehaviour
{
public GameObject hitPrefab;
public GameObject muzzlePrefab;
public float speed;
Rigidbody rb;
Vector3 velocity;
void Awake()
{
TryGetComponent(out rb);
}
void Start()
{
var muzzleEffect = Instantiate(muzzlePrefab, transform.position, transform.rotation);
Destroy(muzzleEffect, 5f);
velocity = transform.forward * speed;
}
void FixedUpdate()
{
var displacement = velocity * Time.deltaTime;
rb.MovePosition(rb.position + displacement);
}
void OnCollisionEnter(Collision other)
{
var hitEffect = Instantiate(hitPrefab, other.GetContact(0).point, Quaternion.identity);
Destroy(hitEffect, 5f);
Destroy(gameObject);
}
}
using UnityEditor;
using UnityEngine;
public class Turret : MonoBehaviour
{
public Gun gun;
public MountPoint[] mountPoints;
public Transform target;
void OnDrawGizmos()
{
#if UNITY_EDITOR
if (!target) return;
var dashLineSize = 2f;
foreach (var mountPoint in mountPoints)
{
var hardpoint = mountPoint.transform;
var from = Quaternion.AngleAxis(-mountPoint.angleLimit / 2, hardpoint.up) * hardpoint.forward;
var projection = Vector3.ProjectOnPlane(target.position - hardpoint.position, hardpoint.up);
// projection line
Handles.color = Color.white;
Handles.DrawDottedLine(target.position, hardpoint.position + projection, dashLineSize);
// do not draw target indicator when out of angle
if (Vector3.Angle(hardpoint.forward, projection) > mountPoint.angleLimit / 2) return;
// target line
Handles.color = Color.red;
Handles.DrawLine(hardpoint.position, hardpoint.position + projection);
// range line
Handles.color = Color.green;
Handles.DrawWireArc(hardpoint.position, hardpoint.up, from, mountPoint.angleLimit, projection.magnitude);
Handles.DrawSolidDisc(hardpoint.position + projection, hardpoint.up, .5f);
#endif
}
}
void Update()
{
// do nothing when no target
if (!target) return;
// aim target
var aimed = true;
foreach (var mountPoint in mountPoints)
{
if (!mountPoint.Aim(target.position))
{
aimed = false;
}
}
// shoot when aimed
if (aimed)
{
gun.Fire();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment