- Home /
How To Access Children of a Parent Object
Hi all,
I'm trying to build something that looks for the closest gameobject to the player (in this case a weapon) and fulfilling a set of conditions draws a ray between two 'attach points'.
What I've done doesn't seem to work, so how best might I access the children of my known objects 'player' and 'closest_weapon'?
The end result will create a force to drag the weapon to the player, align the gun to the player, and set the gun as a child of the player (much easier than rebuilding the floating physics wow-factor script I did for the main player for each weapon I make).
At the moment the code properly recognises the nearest weapon object, but freezes the player in place with no visible ray being drawn upon setting the boolean to be true. I assume this is because it's getting confused as to where to draw the line or something.
Cheers for your time!
Popupirate
using UnityEngine;
using System.Collections;
public class Weapon_Control_Script : MonoBehaviour {
public GameObject closest_weapon;
public bool attach_weapon;
public float distance;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (attach_weapon == false) {
SearchForWeapons();
}
if (attach_weapon == true) {
AttachWeapon();
}
}
void AttachWeapon(){ //Look Here!
Transform p_trans = transform.FindChild ("PlayerAttachPoint");
Transform w_trans = closest_weapon.transform.FindChild ("WeaponAttachPoint");
Vector3 player_attach_vect = new Vector3 (p_trans.position.x, p_trans.position.y, p_trans.position.z);
Vector3 weapon_attach_vect = new Vector3 (w_trans.position.x, w_trans.position.y, w_trans.position.z);
Vector3 direction = weapon_attach_vect - player_attach_vect;
Debug.DrawRay (player_attach_vect, direction, Color.green);
//closest_weapon.rigidbody.AddForce (-direction * 4);
}
void SearchForWeapons(){ //This works lovely jubly
GameObject[] weapons = GameObject.FindGameObjectsWithTag ("Weapon");
distance = Mathf.Infinity;
for (int i=0; i<weapons.Length; i++) {
Vector3 diff_vect = weapons [i].transform.position - transform.position;
float diff_abs = Mathf.Abs (diff_vect.sqrMagnitude);
if (diff_abs < distance) {
closest_weapon = weapons [i];
distance = diff_abs;
}
}
Debug.Log (closest_weapon.name);
}
}
I don't exactly understand what isn't working. Have you tried passing a duration value to DrawRay like this:
Debug.DrawRay (player_attach_vect, direction, Color.green, 1.0f);
Also you can use
Vector3 player_attach_vect = p_trans.position;
ins$$anonymous$$d of
Vector3 player_attach_vect = new Vector3 (p_trans.position.x, p_trans.position.y, p_trans.position.z);
Hi $$anonymous$$ayelGee, Thanks very much for this reply. The second of your suggestions will be very useful.
$$anonymous$$y problem is that despite the fact the script appears to run correctly, no visible debug ray was drawn between my two objects. I assumed this was because it hadn't found my two child objects. I think you can understand my confusion- the script would tell me something was up if the child objects weren't found and vectors are clearly being generated, but no ray. Also the mouse input stops upon setting the boolean attach_weapon=true in the Inspector.
Hope this provides some context!
Cheers,
Popupirate
$$anonymous$$aybe the ray get drawn only one frame and thus is hard to see.
Thanks Cherno, but I tried setting the fourth overload variable that was suggested by $$anonymous$$ayelGee of Debug.Drawray to both 1f and 100f with no effect. The mouse input still freezes and no green ray is drawn between the objects in question.
Answer by awest · Oct 07, 2014 at 03:36 AM
I see a couple issues. You are calling GameObject.Find every single frame (this is very slow and will cause lag in larger projects) and I don't see where you set attach_weapon to true or false. I would start by altering the script like this to run faster. I also added a Debug after DrawRay to check for expected values and set the fifth argument in DrawRay to show through any foreground. Also just to be sure, you know DrawRay only shows in the scene view, not the game window?
using UnityEngine;
using System.Collections;
public class Weapon_Control_Script : MonoBehaviour {
public GameObject closest_weapon;
public bool attach_weapon;
public float distance;
private Transform p_trans;
private Transform w_trans;
private GameObject[] weapons;
void Start () { //I'm assuming these wont change at runtime.
p_trans = transform.FindChild ("PlayerAttachPoint");
weapons = GameObject.FindGameObjectsWithTag ("Weapon");
}
// Update is called once per frame
void Update () {
if (attach_weapon == false) {
SearchForWeapons();
}
if (attach_weapon == true) {
AttachWeapon();
}
}
void AttachWeapon(){ //Look Here!
Vector3 player_attach_vect = p_trans.position;
Vector3 weapon_attach_vect = w_trans.position;
Vector3 direction = weapon_attach_vect - player_attach_vect;
Debug.DrawRay (player_attach_vect, direction, Color.green, 1.0f, false);
//closest_weapon.rigidbody.AddForce (-direction * 4);
Debug.Log(player_attach_vect+", "+direction);
}
void SearchForWeapons(){ //This works lovely jubly
distance = Mathf.Infinity;
for (int i=0; i<weapons.Length; i++) {
Vector3 diff_vect = weapons [i].transform.position - transform.position;
float diff_abs = Mathf.Abs (diff_vect.sqrMagnitude);
if (diff_abs < distance) {
closest_weapon = weapons [i];
distance = diff_abs;
}
}
if (w_trans == null || w_trans.parent.name != closest_weapon.name) w_trans = closest_weapon.transform.FindChild("WeaponAttachPoint");
Debug.Log (closest_weapon.name+" distance: "+distance);
}
}
I tested this script in a project with only the necessary elements and it worked as expected. Let me know if you have any questions about what I changed. Also, if the weapons are created dynamically, I can suggest alternatives to assigning them at the start.
While there is no visible green line being drawn between the objects, it is returning a debug of the vectors which is about the same. I really wanted to put a particle effect along the beam so it looks like a tractor beam or something.
Didn;t realise that I had to keep changing the name of the object w_trans while in the first loop.
You hit the nail on the head as to why i wanted it to update per-frame, since weapons that haven't respawned yet will disappear and reappear in the array. How might I go about doing this dynamically without searching each frame (not that it seemed to hinder my performance too much, but there we go). ## Heading ##
You can to use the vector3 to update particle velocity so you're on the right track there.
Which ever script you use to respawn/create the weapons can add them to the weapons array. However, since arrays can't be resized it would be easier to code if you use a list.
You can also have an empty object that all weapons are children of. When the player attempts to get a weapon you can get all children's transforms from the empty and cycle through to find the closest. When weapons aren't parented to the player, they can auto parent themselves to the empty.
Your answer
Follow this Question
Related Questions
Make a simple tree 1 Answer
Detach child and add force 0 Answers
Getting variable data from Parent 1 Answer
How do I find a child object in a hierarchy of children? 1 Answer
How do I allocate a parent to a gameobject that just got instantiated? 2 Answers