Reputation: 2274
I'm new to Unity and have a problem I can't figure out. I want objects to spawn randomly at a distance of 20 from a FPS player. You could say the objects need to spawn on the surface of a half sphere with the player as the center. But: not all of that sphere can be used. The "highest" part is too high for objects to spawn, so basically it's a sphere with the top cut off.
What I tried:
thePosition = Random.onUnitSphere * 20 + object2.transform.position;
Obviously, this takes into account the whole sphere (should be only half a sphere) and doesn't take into account the "cut off" part.
So I thought: I basically want to make a ray that can pivot on the ground (so the max angle is 360°), and can go up and down, with a max angle of 90°. Think of it like a canon that can turn (pivot) and go up/down with an angle. Here's an image of what I mean:
So I tried:
Vector3 raydirection = new Vector3 (1f, 1f, 0);
raydirection = Quaternion.Euler (45, 0, 0) * raydirection;
Ray ray = new Ray (player.transform.position, raydirection);
thePosition = ray.GetPoint (20);
But that doesn't allow me to control the pivot angle (angle 1) and the "up-down" angle (angle 2) separately.
So my question is: how can I make it so that I can control both angles of this ray? Because if I can do that, I can just take a random number between 0 and 360 for the pivoting part, and between 0 and 90 for the up/down part. Any help is much appreciated!
Upvotes: 0
Views: 101
Reputation: 10720
I want objects to spawn randomly at a distance of 20 from a FPS player.
What I understood from this is that you want to spawn objects on the ground, distant 20 units away from the player, in random directions.
You could say the objects need to spawn on the surface of a half sphere with the player as the center.
Now, this is just another way to make things complex. No need to use the sphere to solve this.
If you want to spawn objects on the surface, easiest solution will be to get a random angle in relation with Vector3.up
and walk for 20 units to find the desired point.
Script:
public class Spawner : MonoBehaviour
{
public Transform player;
public Transform prefab;
[Range(10,50)]
public float distance = 20f;
IEnumerator Start()
{
while (true)
{
yield return new WaitForSeconds(0.05f);
Spawn();
}
}
[ContextMenu("Spawn")]
public void Spawn()
{
Vector3 spawnPoint = FindPoint(player.position, distance, Random.Range(0, 360));
Instantiate(prefab, spawnPoint, Quaternion.identity, transform);
}
[ContextMenu("Clear")]
public void Clear()
{
foreach (var item in transform.GetComponentsInChildren<Transform>())
{
if (item != transform)
DestroyImmediate(item.gameObject);
}
}
Vector3 FindPoint(Vector3 center, float radius, int angle)
{
return center + Quaternion.AngleAxis(angle, Vector3.up) * (Vector3.right * radius);
}
}
Result:
Calculates random point based on player's position:
Hope this helps :)
Upvotes: 2
Reputation: 13394
Coincidentally, I needed something very similar to this. The following Behavior will spawn a certain prefab (objectToSpawn
) exactly spawnCount
times within the set parameters.
The helper class (bottom code) generates a Vector from Yaw, Pitch and a Vector (basically the distance in your case).
What it does:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomSpawner : MonoBehaviour {
public GameObject objectToSpawn;
public int spawnCount;
public float minDistance = 2;
public float maxDistance = 10;
public float minPitchDegrees = 0;
public float maxPitchDegrees = 45;
public float minYawDegrees = -180;
public float maxYawDegrees = 180;
void Start ()
{
for (int i = 0; i < spawnCount; i++)
{
float distance = minDistance + Random.value * (maxDistance - minDistance);
float yaw = minYawDegrees + Random.value * (maxYawDegrees - minYawDegrees);
float pitch = minPitchDegrees + Random.value * (maxPitchDegrees - minPitchDegrees);
Vector3 position = RotationHelper.ConvertYawPitch (Vector3.forward * distance, yaw, pitch);
Instantiate (objectToSpawn, position, Quaternion.identity);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class RotationHelper {
public static Vector3 ConvertYawPitch(Vector3 vector, float yaw, float pitch)
{
Quaternion yawRotation = Quaternion.AngleAxis (yaw, Vector3.up);
Vector3 yawedZAxis = yawRotation * Vector3.left;
Quaternion pitchRotation = Quaternion.AngleAxis (pitch, yawedZAxis);
Vector3 yawedVector = yawRotation * vector;
Vector3 position = pitchRotation * yawedVector;
return position;
}
}
In your specific case, the parameters should be:
minDistance
= 20maxDistance
= 20minPitchDegrees
= 0maxPitchDegrees
= 0-90, whatever the angle is after you "cut off the top"minYawDegrees
= -180maxYawDegrees
= 180Upvotes: 2