I'm making top down shooter game! Every 3-5second enemies spawn in random positions. I've managed this with Random.Range and pixels. But sometimes enemies spawn near the player or at exact position. Is there any way to make bots not spawn near the player? This problem is very critical for my project because if enemy even touches the player, game is over. Here's my script:
IEnumerator SpawnNext()
{
float randX = Random.Range(-8.638889f, 8.638889f);
float randY = Random.Range(-4.5f, 4.75f);
GameObject plt = Instantiate(enemy);
plt.transform.position = new Vector3(randX, randY, 0);
yield return new WaitForSeconds(1f);
}
Use a circle-centric random value. In this method, I normalized a random point on a circle and multiplied it by a random distance range. Adding the value to the main player will give the desired result.
var direction = Random.insideUnitCircle.normalized;
var distance = Random.Range(7, 15); // for e.g 7 is min and 15 max
var pos = direction * distance;
GameObject plt = Instantiate(enemy);
plt.transform.position = player.transform.position + new Vector3(pos.x, pos.y);
Related
Currently I made bullet shoot from players position. Problem is that it shoots from player's center and not from the gun. I changed position of the bullet to make it shoot out from the gun. But the problem is that, when I start to rotate the player, bullet copies the rotation but not the position of the gun. It just stays on the same place. Here's my code:
public Transform firePoint;
public GameObject bulletPrefab;
public float bulletForce = 20f;
public void Shoot()
{
Vector3 newPosition = new Vector3(firePoint.position.x + 1, firePoint.position.y - 0.1f, firePoint.position.z);
GameObject bullet = Instantiate(bulletPrefab, newPosition, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.right * bulletForce, ForceMode2D.Impulse);
yield return new WaitForSeconds(0.5f);
}
Your issue is that you have hard-coded offset (x = 1, y = -0.1f) change. When you rotate your player 90 degrees, the offset for gun end becomes different.
There are two solutions for this:
Solution #1
Place your fire point Transform at the tip of the gun, make it child of the gun. That way the Transform will always follow the end of the gun.
Now, for instantiating, you can use firepoint.position without any modifications.
There are some drawbacks to this, mainly having strict objects hierarchy and it becomes harder to dynamically change guns as you will have to find and reassign fire point for each of them.
Solution #2
Have Vector3 firePointOffset;.
Once instantiating, calcualte the position of the fire point by doing
var firePointPosition = playerTransform.position + Vector3.Scale(playerTransform.forward, firePointOffset)`;
transform.forward returns Vector3 that points, well, forward for that specific transform. Vector3.Scale allows multiplying two vectors x * x, y * y, z * z;
I'm new to Unity2D (Unity 5.0.2f1) and have been searching for a solution which I'm sure is staring me in the face!
I have a game object (essentially a road) like below (DirtTrack1):
I have a spawner which spawns GameObjects (vehicles). I want to spawn those vehicles over this road.
I have tried the following code to do this, essentially trying to spawn the vehicle within the Y-axis area of the road by getting the bottom Y co-ordinate of the road and the top Y co-ordinate, so I get the min and max vertical positions of where I can place the vehicle:
void FixedUpdate() {
// Repeat spawning after the period spawn
// route has finished.
if (!_inSpawningIteration)
StartCoroutine (SpawnVehiclePeriodically());
}
IEnumerator SpawnVehiclePeriodically()
{
// First, get the height of the vehicle and road.
float vehicleHeightHalf = vehiclePreFab.GetComponent<SpriteRenderer>().bounds.size.y / 2f;
float roadHeightHalf = roadObject.GetComponent<SpriteRenderer>().bounds.size.y / 2f;
float roadTopY = roadObject.transform.position.y + roadHeightHalf;
float roadBottomY = roadObject.transform.position.y - roadHeightHalf;
// Next, ensure that maxY is within bounds of this farm vehicle.
roadMaxY = roadTopY - vehicleHeightHalf;
roadMinY = roadBottomY + vehicleHeightHalf;
// Set the position and spawn.
Vector3 newPosition = new Vector3 (Const_RoadItemsPositionX, randomY, 0f);
GameObject vehicle = (GameObject)GameObject.Instantiate (vehiclePreFab, newPosition, Quaternion.identity);
}
This does spawn randomly but most times it is always not within the road itself. It is either part on the road or at the outside edge of it.
I can't figure out what I'm doing wrong here but I'm sure it is something very simple!
Tick the kinematic check of your vehicle, physics may be moving it out of the road if you don't do that.
You are using localPosition. From documentation:
Position of the transform relative to the parent transform.
If the transform has no parent, it is the same as Transform.position.
Looking at your scene, your road has a parent object and the relative position you are getting might be messing up with the spawn position of cars.
So basically I have a spawning script (2D game) that spawns in a enemy after spawn delay. I've also adding an array of enemy prefabs so that the SpawnerScript will spawn in a random enemy. However I'm having some problems with spawning in the prefabs in a random position within a transform (a.k.a: a 3D cube). You see My spawner isn't spawning in anything when I play the game, I made sure that I have included the size of how many enemies I want to spawn in. and made sure I have attach my prefabs. I also made sure that my unity project file hasn't got a bug. Maybe my code is wrong, i'm not sure.
My SpawnerScript:
public float RateOfSpawn = 1;
public float spawnTime = 2;
public GameObject[] enemy;
void Start(){
InvokeRepeating ("addEnemy", spawnTime, spawnTime);
}
void Spawn () {
// Random position within this transform- 3Dcube
var x1 = transform.position.x - GetComponent<Renderer> ().bounds.size.x / 2;
var x2 = transform.position.x + GetComponent<Renderer> ().bounds.size.x / 2;
var spawnPoint = new Vector2 (Random.Range (x1, x2), transform.position.y);
int enemyIndex = enemy.Length;
Instantiate (enemy[enemyIndex],spawnPoint,Quaternion.identity);
}
}
Thank you :)
You have to call the proper function to make it work.
void Start()
{
InvokeRepeating ("Spawn", spawnTime, spawnTime);
}
You have to call "Spawn" instead of "addEnemy".
Also change Instanatiate for proper instantiation.
Instantiate (enemy[Random.Range (0, enemyIndex)], spawnPoint, Quaternion.identity);
enemy[Random.Range (0, enemyIndex)] helps you choose random enemy from array of enemies' index 0 to enemyIndex-1.
The cause of exception is putting the length of array as index. Max Index limit is always length-1.
I am trying to create an aiming system in Unity, where index finger is being used to control a crosshair. The game is being played with Oculus and Leap Motion is mounted on to the Oculus headset.
I have tried to calculate the position for the crosshair based on the angle of the index finger and draw a ray based on a given distance. I have also tried calculating the crosshair location just based on the direction of the index finger and given distance like this:
Vector3 targetPoint = direction * direction;
Here is what I have tried:
void Start () {
crossHair = GameObject.Find("Crosshair Component");
myCamera = GameObject.Find("CenterEyeAnchor");
target = crossHair.transform;
controller = new Controller();
indexFinger = new Finger();
void Update () {
crossHair.transform.position = myCamera.transform.position;
frame = controller.Frame();
List<Hand> handList = new List<Hand>();
for (int h = 0; h < frame.Hands.Count; h++)
{
Hand leapHand = frame.Hands[h];
handList.Add(leapHand);
}
if (handList != null && frame.Hands.Count > 0) {
indexFinger = frame.Hands[0].Fingers[(int)Finger.FingerType.TYPE_INDEX];
if (indexFinger.IsExtended)
{
Vector3 fingerTipPos = indexFinger.TipPosition.ToUnityScaled();
Vector3 originAngle = indexFinger.TipPosition.ToUnityScaled();
Vector3 targetAngle = crossHair.transform.position;
float distance = 1;
Vector3 direction = indexFinger.Direction.ToUnityScaled();
Ray rayToTest = new Ray(originAngle, targetAngle);
Vector3 targetPoint = rayToTest.GetPoint(distance);
//Problem is here. How should these targetPoint values be used to calculate correct position for the crosshair?
crossHair.transform.position = new Vector3(crossHair.transform.position.x + (targetPoint.x), y,
crossHair.transform.position.z + (targetPoint.z));
}
}
}
}
With similar calculations as these I have been able to move the crosshair accordingly on horizontal level by modifying x and z values but the y-axis seems to be the biggest problem. Y-axis seems to always receive too low values.
The crosshair element is placed as a child element for the CenterEyeAnchor camera object in Unity.
So questions are: Is the way of calculating the target point position right as I have been trying to make it?
What kind of calculations would I have to make for the crosshairs position based on the new target point value to make it behave accordingly to the index finger movement? Scaling factors for the values?
Pictures of the project setup and current object positions attached.
Here is the image for the setup of objects
Here is the image of the crosshair's false position
I am not sure how to approach this problem or whether there are any built in Unity functions that can help with this problem so any advice is appreciated.
Here is an image that'll help describe what I want to do:
I want to spawn Game Objects around a given point within the limits of a set radius. However their position in this radius should be randomly selected. This position should have the same Y axis as the origin point (which is on the ground). The next main problem is that each object should not clash and overlap another game object and should not enter their personal space (the orange circle).
My code so far isn't great:
public class Spawner : MonoBehaviour {
public int spawnRadius = 30; // not sure how large this is yet..
public int agentRadius = 5; // agent's personal space
public GameObject agent; // added in Unity GUI
Vector3 originPoint;
void CreateGroup() {
GameObject spawner = GetRandomSpawnPoint ();
originPoint = spawner.gameObject.transform.position;
for (int i = 0; i < groupSize; i++) {
CreateAgent ();
}
}
public void CreateAgent() {
float directionFacing = Random.Range (0f, 360f);
// need to pick a random position around originPoint but inside spawnRadius
// must not be too close to another agent inside spawnRadius
Instantiate (agent, originPoint, Quaternion.Euler (new Vector3 (0f, directionFacing, 0f)));
}
}
Thank you for any advice you can offer!
For personal space you can use colliders to avoid overlapping.
For spawning in circle you can use Random.insideUnitSphere. You can modify your method as,
public void CreateAgent() {
float directionFacing = Random.Range (0f, 360f);
// need to pick a random position around originPoint but inside spawnRadius
// must not be too close to another agent inside spawnRadius
Vector3 point = (Random.insideUnitSphere * spawnRadius) + originPoint;
Instantiate (agent, point, Quaternion.Euler (new Vector3 (0f, directionFacing, 0f)));
}
Hope this helps you.
For spawning the object within the circle, you could define the radius of your spawn circle and just add random numbers between -radius and radius to the position of the spawner like this:
float radius = 5f;
originPoint = spawner.gameObject.transform.position;
originPoint.x += Random.Range(-radius, radius);
originPoint.z += Random.Range(-radius, radius);
For detecting if the spawn point is to close to another game object, how about checking the distance between them like so:
if(Vector3.Distance(originPoint, otherGameObject.transform.position < personalSpaceRadius)
{
// pick new origin Point
}
I'm not that skilled in unity3d, so sry for maybe not the best answer^^
Also:
To check which gameobjects are in the spawn area in the first place, you could use the Physics.OverlapSphere Function defined here:
http://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html