0
\$\begingroup\$

I have a game object whose prefab is structured a very specific way. It is a conveyor belt. I intend to arrange them end-to-end and animate them all at once using a script. Right now I am trying to get the normalized heading vector between two children, TargetStart and TargetEnd (see images below):

TargetStart TargetEnd

You can see that both of these objects are children of the prefab's first child. Because all of these instances will be structured the same, I want to compute the heading for the conveyor belt by accessing the locations of these children by their indices relative to the parent (which sounds like it should be simple and should be more efficient than searching by name or tag). I am anticipating a structure like this (pseudo-code):

// heading = targetEnd's position - targetStart's position
vector3 heading = gameObject.GetChild[0][1].position - gameObject.GetChild[0][0].position;
vector3 direction = heading / heading.magnitude;

How can this be done? I would like to know this so I can access any child I need to for any object by the child's index.

\$\endgroup\$
2
\$\begingroup\$

Accessing by index is a little fragile, if the structure of your prefab were ever to change.

As your object is a prefab, you might consider adding fields to your ConveyorBelt script for the start and end position objects instead, like so:

public class ConveyorBelt : MonoBehaviour
{
    [SerializeField] private Transform targetStart;
    [SerializeField] private Transform targetEnd;
// . . . 
}

You'd then access targetStart.position and similar, caching the values as you are already if it becomes a performance concern.


Unity will persist references to objects which are part of the same prefab, so every instance will reference its own start / end points. This allows a bit more flexibility for any future changes to your object structure.

\$\endgroup\$
0
\$\begingroup\$

Whelp, I feel silly now. I thought I kept stumbling over this before but the answer is in the documentation example. This is how I am doing it:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConveyorBelt : MonoBehaviour
{
    public bool isMoving = true;
    public float speed = 0.1f;
    private float offset = 0f;
    private Vector3 targetStart;
    private Vector3 targetEnd;
    private Vector3 heading;
    private Vector3 direction;
    // Start is called before the first frame update
    void Start()
    {
        targetStart = gameObject.transform.GetChild(0).GetChild(0).position;
        targetEnd = gameObject.transform.GetChild(0).GetChild(1).position;
        heading = targetEnd - targetStart;
        direction = heading / heading.magnitude;
    }

    // Update is called once per frame
    void Update()
    {
        if (isMoving == true)
        {
            MoveBelt();
        }
    }

    public void MoveBelt()
    {
        offset += (Time.deltaTime * speed);
        if (Mathf.Abs(offset) > 999)
        {
            offset %= 1f; //thought this might save memory, maybe not
        }
        gameObject.GetComponent<Renderer>().material.SetTextureOffset("_MainTex", new Vector2(0, offset));
    }

    public void StopBelt()
    {
        isMoving = false;
    }

    public void OnTriggerStay(Collider other)
    {
        if (other.attachedRigidbody && isMoving == true)
        {
            other.transform.position = other.transform.position + direction * Time.deltaTime / (2 * Mathf.PI * 0.25f + 3f);
        }
    }
    public void SetSpeed(float newSpeed)
    {
        speed = newSpeed;
    }
}

Animation of the script in action, correctly transporting the cube along the conveyor

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.