Rotation of moving prefabs

I’m trying to create a game where as a player you need to dodge objects which are moving downwards. I have objects moving on the right and left side of the screen. By default my prefab is created to spawn on the right side and face right. And I need to mirror this prefab onto the left side correctly.
I instantiate prefabs and apply force to them to move downwards:

// SpawnManager.cs
Instantiate(obstaclePrefabs, spawnPosLeft, transform.rotation);
// MoveDown.cs
void Update()
{
    if (playerPositionScript.gameOver == false)
    {
        transform.Translate(Vector3.down * speed * Time.deltaTime);
    }
}

I’ve tried to change prefab rotation:
1.

Instantiate(obstaclePrefabs, spawnPosLeft, transform.rotation = Quaternion.Euler(0, 0, 180));
  1. I’ve added an empty gameObject inside my prefab and tried to rotate it:
 public GameObject obstaclePrefabs;
private GameObject obstacleRotation;

void Start()
{
obstacleRotation = obstaclePrefabs.GetComponentInChildren<GameObject>();
InvokeRepeating("SpawnRandomObstacle", 0, delaySpawn);
}

private void SpawnRandomObstacle()
{
obstacleRotation.transform.rotation = Quaternion.Euler(0, 0, 180);
Instantiate(obstaclePrefabs, spawnPosLeft, transform.rotation);
}

What went wrong:

  1. It wasn’t correct because I’m constantly applying force from top to bottom and when I rotate an object it goes from bottom to top.
  2. It just can’t find my empty gameObject inside of the obstaclePrefab and nothing spawns.

Please, check the documentation for the Translate method. This method also accepts a second parameter, which determines the space relative to which the movement will occur. By default, this space is the object’s own space, but if you want to move relative to the world (global space), you need to set this parameter to Space.World.

1 Like

There’s a lot of subtle critical problems with the above code.

For instance, line 6 obtains the GameObject of the PREFAB on disk, but attempts to do so with GetComponentInChildren()

GameObjects are not Components so I’m surprised the above code even compiles.

If it compiles, it is likely to return null when run.

Second of all, you don’t want the prefab.

You want the instance of the prefab, which you create on line 13 with Instantiate.

But you don’t save the return value of Instantiate!

Instead, line 12 manipulates the transform of the prefab on disk…

So yeah, it is all tangled up and I’m surprised any of it works.

In summary, to fix this:

  • use good variable names: ThingPrefab and ThingInstance are a great start

  • make ThingPrefab public and ThingInstance private to help you keep it straight.

  • NEVER modify the ThingPrefab.

  • ONLY modify the ThingInstance

  • create the instance with ThingInstance = Instantiate( ThingPrefab);

1 Like

GameObjects have all the same GetComponent methods that components do. In fact, Component.GetComponent just calls GameObject.GetComponent and so on.

It would actually return a component instance if one exists. You can reference child game objects of prefabs; you can even serialize references to them! (just not via vanilla inspector means)

But yes they should be operating on the instance and not the prefab in this instance.

That’s not quite what I’m talking about.

This was OP’s code from above:

obstacleRotation = obstaclePrefabs.GetComponentInChildren<GameObject>();

^ ^ ^ the presence of GameObject in the place of T is what I question here:. :slight_smile:

Here is my test right now:

        var x = GetComponent<GameObject>();
        Debug.Log(x);

and that don’t work so well!

9773175--1400808--Screen Shot 2024-04-15 at 7.45.14 PM.png

I expect GetComponentInChildren would similarly fail. GameObject is not a Component

1 Like

Right completely missed that detail. My bad.

1 Like

For me, Unity throws an exception at runtime: ArgumentException: GetComponent requires that the requested component ‘GameObject’ derives from MonoBehaviour or Component or is an interface.

2 Likes