- Home /
Getting the transform from a GameObject list
Alright, so I'm working on an aim assist system, and the hurdle I'm running into is being unable to have the transform from a list of enemies in a box collider zone (which is a child to the camera). Essentially what I'm trying to do is aim a weapon (also a child to the camera) to aim at the closest enemy in the zone. I'm fairly certain I can figure out how to rotate the weapon to the nearest enemy, I already had debug code set up to to test rotating the weapon independent of the camera, but my problem now is I can't get the transform of the nearest enemy from the aim assist script in the camera script to aim the weapon towards it. The error I get is detailed at the bottom.
Code for the camera script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraLook : MonoBehaviour
{
[SerializeField] private float mSensX = 8f;
[SerializeField] private float mSensY = 8f;
[SerializeField] Transform playerCamera;
[SerializeField] Transform orientation;
[SerializeField] PlayerBehavior playerBH;
[SerializeField] Transform weapon;
[SerializeField] Transform autoAim; //this is the box collider zone, which has the aim assist script attached to it
float mouseX;
float mouseY;
float mouseMultiplier = 1.4f;
float mRotationX;
float mRotationY;
float rotateAmountX;
float rotateAmountY;
private void Start()
{
//
}
private void Update()
{
//Autoaiming debug code starts here
if (Input.GetKey(KeyCode.L))
{
rotateAmountY += 50 * Time.deltaTime;
}
if (Input.GetKey(KeyCode.J))
{
rotateAmountY += -50 * Time.deltaTime;
}
if (Input.GetKey(KeyCode.K))
{
rotateAmountX += 50 * Time.deltaTime;
}
if (Input.GetKey(KeyCode.I))
{
rotateAmountX += -50 * Time.deltaTime;
}
//and ends here
MouseInput();
playerCamera.transform.localRotation = Quaternion.Euler(mRotationX, mRotationY, playerBH.cameraCurrentTilt);
//weapon.transform.rotation = Quaternion.Euler(mRotationX + rotateAmountX, mRotationY + rotateAmountY, 0); //commented out for now, only worked for debug testing
Quaternion targetDirection = Quaternion.LookRotation(autoAim.closestEnemyInDirection.transform.position - transform.position); //the line where the error appears, I'm not sure if this is even the correct way of getting the results I want, but it's one of a few ways that produces the error. The exact error is written out below.
orientation.transform.rotation = Quaternion.Euler(0, mRotationY, 0);
}
void MouseInput()
{
mouseX = Input.GetAxisRaw("Mouse X");
mouseY = Input.GetAxisRaw("Mouse Y");
mRotationY += mouseX * mSensX * mouseMultiplier;
mRotationX -= mouseY * mSensY * mouseMultiplier;
mRotationX = Mathf.Clamp(mRotationX, -90f, 90f);
}
}
Code for the aim assist script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AutoAim : MonoBehaviour
{
public List<GameObject> enemies = new List<GameObject>();
public GameObject closestEnemyInDirection;
public Transform body;
Transform closestEnemyTransform;
void Start()
{
}
public void FindClosestGameObject()
{
GameObject closest = null;
float distance = 400f;
Vector3 position = body.transform.position;
foreach (GameObject go in enemies)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance)
{
closest = go;
distance = curDistance;
}
}
closestEnemyInDirection = closest;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Enemy")
{
for (int i = 0; i < enemies.Count; i++)
{
if (other.gameObject == enemies[i])
{
return;
}
}
enemies.Add(other.gameObject);
FindClosestGameObject();
}
}
void OnTriggerExit(Collider other)
{
if (other.tag == "Enemy")
{
for (int i = 0; i < enemies.Count; i++)
{
if (other.gameObject == enemies[i])
{
if (enemies[i] == closestEnemyInDirection)
{
closestEnemyInDirection = null;
}
enemies.RemoveAt(i);
}
}
}
}
}
The error I get in the camera script is: 'Transform' does not contain a definition for 'closestEnemyInDirection' and no accessible extension method 'closestEnemyDirection' accepting a first argument of type Transform could be found (are you missng a using directive or an assembly reference?)
Assistance would be appreciated, I'm fairly inexperienced with Unity/C#, and I'm at an impass with this.
Answer by AaronBacon · Aug 15, 2021 at 10:24 AM
So the problem line is
Quaternion targetDirection =Quaternion.LookRotation(autoAim.closestEnemyInDirection.transform.position - transform.position);
the issue being the part "autoAim.closestEnemyInDirection.transform.position"
the problem is that "autoAim" is a transform, while "AutoAim" is the class that contains the "closestEnemyinDirection" variable. So I have to assume what you actually wanted to do was:
Quaternion targetDirection =Quaternion.LookRotation(autoAim.GetComponent<AutoAim>().closestEnemyInDirection.transform.position - transform.position);
Bear in mind that this is massively inefficient, so what you'd probably want to do is store a reference to the AutoAim Component:
public class CameraLook : MonoBehaviour
{
[SerializeField] Transform autoAim;
public AutoAim aimComponent;
private void Start()
{
aimComponent = autoAim.GetComponent<AutoAim>();
}
}
//... Then when you need it:
Quaternion targetDirection =Quaternion.LookRotation(aimComponent.closestEnemyInDirection.transform.position - transform.position);
Having said all that, might be worth looking at https://docs.unity3d.com/ScriptReference/Transform.LookAt.html , its possible it may suit your purpose better. Let me know if you get any more errors.
Answer by CircuitryCreature · Aug 16, 2021 at 02:07 AM
@AaronBacon This worked fantastically, thank you! There's only one issue that I'm having, though it doesn't come up as an error. For a reason unknown to me, the weapon aims above the center of the target objects. Here's a video showing what I mean.
And here's the updated code for the camera script: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class CameraLook : MonoBehaviour
{
[SerializeField] private float mSensX = 8f;
[SerializeField] private float mSensY = 8f;
[SerializeField] Transform playerCamera;
[SerializeField] Transform orientation;
[SerializeField] PlayerBehavior playerBH;
[SerializeField] Transform weapon;
[SerializeField] Transform autoAim;
public AutoAim aimComponent;
float mouseX;
float mouseY;
float mouseMultiplier = 1.4f;
float mRotationX;
float mRotationY;
private void Start()
{
aimComponent = autoAim.GetComponent<AutoAim>();
}
private void Update()
{
MouseInput();
playerCamera.transform.localRotation = Quaternion.Euler(mRotationX, mRotationY, playerBH.cameraCurrentTilt);
orientation.transform.rotation = Quaternion.Euler(0, mRotationY, 0);
if (aimComponent.closestEnemyInDirection != null)
{
Quaternion targetDirection = Quaternion.LookRotation(aimComponent.closestEnemyInDirection.transform.position - transform.position);
weapon.transform.rotation = Quaternion.Slerp(weapon.transform.rotation, targetDirection, 10 * Time.deltaTime);
}
else
{
Quaternion targetDirection = Quaternion.Euler(mRotationX, mRotationY, 0);
weapon.transform.rotation = Quaternion.Slerp(weapon.transform.rotation, targetDirection, 10 * Time.deltaTime);
}
}
void MouseInput()
{
mouseX = Input.GetAxisRaw("Mouse X");
mouseY = Input.GetAxisRaw("Mouse Y");
mRotationY += mouseX * mSensX * mouseMultiplier;
mRotationX -= mouseY * mSensY * mouseMultiplier;
mRotationX = Mathf.Clamp(mRotationX, -90f, 90f);
}
}
Hmm, that is a weird one, I suppose if its a consistent amount you could always just have each bullet be adjusted slightly as soon as its created? so you would just need to use https://docs.unity3d.com/ScriptReference/Transform.Rotate.html
Good idea! I was able to set up adjusting the bullet with a variable in the weapon script that would be altered depending if the auto ai$$anonymous$$g was engaged or not. That way if it wasn't, the bullets wouldn't always be at an angle. Though with altering the angle, it would still be offset depending on what angle the camera was. Thankfully this was fixed by adjusting the position upon creation, rather than rotation. public AutoAim aimComponent; public WeaponBehavior weaponScript; private void Start() { aimComponent = autoAim.GetComponent<AutoAim>(); weaponScript = weapon.GetComponent<WeaponBehavior>(); } if (aimComponent.closestEnemyInDirection != null) { Quaternion targetDirection = Quaternion.LookRotation(aimComponent.closestEnemyInDirection.transform.position - transform.position); weapon.transform.rotation = Quaternion.Slerp(weapon.transform.rotation, targetDirection, 10 * Time.deltaTime); weaponScript.aimCompensation = -0.66f; } else { Quaternion targetDirection = Quaternion.Euler(mRotationX, mRotationY, 0); weapon.transform.rotation = Quaternion.Slerp(weapon.transform.rotation, targetDirection, 10 * Time.deltaTime); weaponScript.aimCompensation = 0f; }
And in the weapon script, 'aimCompensation' is always applied on an Instantiate line, since its default state is 0 and can be altered. Thanks again for the help! You've been a real life saver!
Edit: Whoops, didn't realize code in comments would be so unformatted. Oh well.
Ah! I figured out why it was doing that, this bit here Quaternion targetDirection = Quaternion.LookRotation(aimComponent.closestEnemyInDirection.transform.position - transform.position); The transform.position should be weapon.transform.position.
Answer by Deontaegutmann · Aug 16, 2021 at 08:34 AM
Hello, I'm trying to make an aim assist... so far I've managed to populate a list of enemies via onTriggerEnter and checking for an object tag (and depopulate the list via onTriggerExit), but now im trying to find the distance to the nearest enemy. I've found plenty of resources using foreach and returning the shortest distance but I'm struggling to understand where to actually implement this. Any info is appreciated, thanks!