TransWikia.com

How can I spawn random objects on a plane area even if the plane position is not 0,0,0 and how to spawn also with random height?

Game Development Asked by Shamen Raze on January 17, 2021

This is the spawn script :

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

/// <summary>
/// An object spawner
/// </summary>
public class SpawnObject : MonoBehaviour
{
    #region Variables
    // needed for spawning
    [SerializeField]
    GameObject spawnObject;

    [SerializeField]
    GameObject plane;
    
    // spawn control
    const float MinSpawnDelay = 0.1f;
    const float MaxSpawnDelay = 0.5f;
    Timer spawnTimer;

    // spawn location support
    float randomX;
    float randomY;
    float randomZ;

    #endregion

    #region Methods
    /// <summary>
    /// Use this for initialization
    /// </summary>
    void Start()
    {
        plane = GameObject.FindWithTag("Plane");

        // save spawn boundaries for efficiency
        float randomX = Random.Range (plane.transform.position.x - plane.transform.localScale.x / 2, plane.transform.position.x + plane.transform.localScale.x / 2);
        float randomY = Random.Range (plane.transform.position.y - plane.transform.localScale.y / 2, plane.transform.position.y + plane.transform.localScale.y / 2);
        float randomZ = Random.Range (plane.transform.position.y - plane.transform.localScale.z / 2, plane.transform.position.y + plane.transform.localScale.z / 2);

        // create and start timer
        spawnTimer = gameObject.AddComponent<Timer>();
        spawnTimer.Duration = Random.Range(MinSpawnDelay, MaxSpawnDelay);
        spawnTimer.Run();
    }

    /// <summary>
    /// Update is called once per frame
    /// </summary>
    void Update()
    {
        // check for time to spawn a new enemy
        if (spawnTimer.Finished)
        {
            objectSpawn();

            // change spawn timer duration and restart
            spawnTimer.Duration = Random.Range(MinSpawnDelay, MaxSpawnDelay);
            spawnTimer.Run();
        }
        
    }
    
    /// <summary>
    /// Spawns an object at a random location on a plane
    /// </summary>
    void objectSpawn()
    {
        // generate random location and create new object
        Vector3 randomPosition = GetARandomPos(plane);
                                                                  
        Instantiate<GameObject>(spawnObject, randomPosition, Quaternion.identity);   
    
    }

    /// <summary>
    /// Return random position on the plane
    /// </summary>
    public Vector3 GetARandomPos(GameObject plane){

    Mesh planeMesh = plane.GetComponent<MeshFilter>().mesh;
    Bounds bounds = planeMesh.bounds;

    float minX = plane.transform.position.x - plane.transform.localScale.x * bounds.size.x * 0.5f;
    float minZ = plane.transform.position.z - plane.transform.localScale.z * bounds.size.z * 0.5f;

    Vector3 newVec = new Vector3(Random.Range (minX, -minX),
                                 plane.transform.position.y,
                                 Random.Range (minZ, -minZ));
    return newVec;
    }

    #endregion
}

The object script I called it Objectsp :

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

/// <summary>
/// A enemy
/// </summary>
public class Objectsp : MonoBehaviour
{
    #region Variables
    // death support
    const float EnemyLifespanSeconds = 10;
    Timer deathTimer;

    #endregion

    /// <summary>
    /// Use this for initialization
    /// </summary>
    void Start()
    { 
        // create and start timer
        deathTimer = gameObject.AddComponent<Timer>();
        deathTimer.Duration = EnemyLifespanSeconds;
        deathTimer.Run(); 
    }

    /// <summary>
    /// Update is called once per frame
    /// </summary>
    void Update()
    {
        // destroy enemy if death timer finished
        if(deathTimer){
            if (deathTimer.Finished)
            {    
                Destroy(gameObject);       
            }
        }
        
    }
    
}

And the timer script :

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

/// <summary>
/// A timer
/// </summary>
public class Timer : MonoBehaviour
{
    #region Variables
    
    // timer duration
    float totalSeconds = 0;
    
    // timer execution
    float elapsedSeconds = 0;
    bool running = false;
    
    // support for Finished property
    bool started = false;
    
    #endregion
    
    #region Properties
    
    /// <summary>
    /// Sets the duration of the timer
    /// The duration can only be set if the timer isn't currently running
    /// </summary>
    /// <value>duration</value>
    public float Duration
    {
        set
        {
            if (!running)
            {
                totalSeconds = value;
            }
        }
    }
    
    /// <summary>
    /// Gets whether or not the timer has finished running
    /// This property returns false if the timer has never been started
    /// </summary>
    /// <value>true if finished; otherwise, false.</value>
    public bool Finished
    {
        get { return started && !running; } 
    }
    
    /// <summary>
    /// Gets whether or not the timer is currently running
    /// </summary>
    /// <value>true if running; otherwise, false.</value>
    public bool Running
    {
        get { return running; }
    }

    #endregion

    #region Methods

    /// <summary>
    /// Update is called once per frame
    /// </summary>
    void Update()
    {   
        // update timer and check for finished
        if (running)
        {
            elapsedSeconds += Time.deltaTime;
            if (elapsedSeconds >= totalSeconds)
            {
                running = false;
            }
        }
    }
    
    /// <summary>
    /// Runs the timer
    /// Because a timer of 0 duration doesn't really make sense,
    /// the timer only runs if the total seconds is larger than 0
    /// This also makes sure the consumer of the class has actually 
    /// set the duration to something higher than 0
    /// </summary>
    public void Run()
    {   
        // only run with valid duration
        if (totalSeconds > 0)
        {
            started = true;
            running = true;
            elapsedSeconds = 0;
        }
    }
    
    #endregion
}

This is the scene and settings screenshot, and since the plane is not at 0,0,0 the spawn objects are not inside the plane area.
If the plane is at 0,0,0 it will work fine but I want it to work also if the plane is not at 0,0,0 and also to use height.

On the Plane Spawner I attached the Spawn Object script and on the PlanePrefab the Objectsp and the Timer scripts.

Spawner

One Answer

You need to create or move the spawn point to the position you want - set the spawn point to the correct transform.position and it will spawn correctly. The plane spawner is at 0, 0, 0 - and it's spawning correctly - you need to move it to be at the location you want to spawn at (x, y, z).

Answered by Chris Norman on January 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP