I created a simple shooter in Unity and i want to change the position of my Player (FPSController). I can only change the position when i do it in the Prefab but this is useless for me.
If i call functions like "InstantiatePlayer()" where it tries to change the position, the player will be teleported after 0.1 sec back to the old position.
public void InstantiatePlayer()
{
GameObject temp = Instantiate(PlayingplayerPref);
temp.transform.position = new Vector3(31, 6, 7);
}
vgro's solution is ok, but instead of creating a new Quaternion you should use Quaternion.identity, won't do much of a difference here but it's good practice
You can specify the position when on instantiating.
Instantiate(Object PlayingplayerPref, Vector3 position, Quaternion rotation);
If you dont want to specify the rotation just set the quaternion to (0,0,0,0), so you will have
Instantiate(PlayingplayerPref, position, new Quaternion(0,0,0,0);
Hope this helps :)
Related
I have one problem. I want my prefabs to spawn every time my player picks them up. I did research on Google and YouTube and I tried to use the random function and instantiate. I don't know how to use them. I wrote this code I saw on YouTube and my prefab Sphere moves like 1cm to z position. I want to every time when I pick up object or my player go to spawn more of this on the z position. How do I do this?
My smaller script:
public GameObject Sphere;
public float zrange;
// Use this for initialization
void Start () {
RandomPosition();
}
void RandomPosition()
{
zrange = Random.Range(0f, 2f);
this.transform.position = new Vector3(0, 0, zrange);
}
You achieve that by not messing with the x and y values (your code sets them both to 0).
Vector3 p = transform.position;
p.z = zrange;
transform.position = p;
This assumes that your code to instantiate the object is already correctly placing the object. If not, more information is needed.
I ran into an issue with box-casts while developing a 3D game for mobile.
I want to check the path between my player and his target, to avoid him passing through environmental objects (he doesn't have a rigidbody attached and movement is only possible between specific points).
This is the code that I used to check:
private bool CheckPath (Vector3 position, Vector3 target)
{
Vector3 center = Vector3.Lerp(transform.position, target, 0.5f);
Vector3 halfExtents = new Vector3(1, 1, (transform.position - target).magnitude) / 2;
Quaternion rotation = Quaternion.LookRotation((transform.position - target).normalized);
RaycastHit[] rhit = Physics.BoxCastAll(center, halfExtents, (transform.position - target).normalized, rotation);
bool result = rhit.All(r => r.collider.tag != "Environment");
DebugUtilities.BoxCastDebug.DrawBox(center, halfExtents, rotation, result ? Color.green : Color.red, 3);
return result;
}
This code works for the most situations:
But fails, for example for this situation:
To visualize the box-cast I used the script from this Unity Answers link.
I am not sure where the problem lies, although the most likely cause would be a flaw in the debugging script mentioned above, which made me believe that my box-cast call was correct.
I am grateful for every solution, although a simple one would be more appreciated.
Some further information (if needed):
The objects that I want to make impassable are marked with a Environment tag.
I was not the one that wrote the debugging script, it seemed to work at first, so I was fine with it.
Three problems in your code
1.The position variable from the unction parameter is not used. You are instead using transform.position which means that the starting point may be wrong.
Replace all your transform.position with position.
2.You are performing the raycast backwards. It should not be transform.position - target. That should be target - transform.position.
3.Your Physics.BoxCastAll will not work properly since there is no ending to the raycast. Objects behind the starting will be detected by the raycast. Now, if you fix problem #2, the problem will reverse. Now, all the objects in behind the target will also be detected since you did not provide the raycast distance. You can provide the distance with Vector3.Distance(position, target) in the last parameter of the Physics.BoxCastAll function.
Fixed function:
private bool CheckPath(Vector3 position, Vector3 target)
{
Vector3 halfExtents = Vector3.one;
Quaternion rotation = Quaternion.LookRotation(target - position);
Vector3 direction = target - position;
float distance = Vector3.Distance(position, target);
RaycastHit[] rhit = Physics.BoxCastAll(position, halfExtents, direction, rotation, distance);
bool result = rhit.All(r => r.collider.tag != "Environment");
Vector3 center = Vector3.Lerp(position, target, 0.5f);
halfExtents = new Vector3(1, 1, (target - position).magnitude) / 2;
DebugUtilities.DrawBox(center, halfExtents, rotation, result ? Color.green : Color.red);
// Debug.DrawRay(position, direction, result ? Color.green : Color.red);
return result;
}
It's worth setting up 3 objects (Cubes) in order to easily test this function. The first one is from Object (Player). The middle one should be the obstacle with the "Environment" tag. The last one should be the target Object where player is moving to.
Then you can use the script below to test it. Run it and move the obstacle away between the player and the target and it should work as expected.
public GameObject playerObject;
public GameObject targetObject;
void Update()
{
Debug.Log("Path cleared: " + CheckPath(playerObject.transform.position, targetObject.transform.position));
}
You will get the similar result below:
This is my first post, so if I do something wrong, let me know it. Im doing in Unity 5.5 a 2D Car Game, with a topdown view. For the game, i need that some cars have a simple AI Script, just for follow a path. So, I searched in the web something that fits my needs, and found(in my opinion) a really good implementation. Here i let u the project in GitHub, uploaded by the owner of the implementation I suppose: https://github.com/mindcandy/lu-racer
So in a few words, we create a Path with empty GameObjects and the respective colliders, we have to have a car(obviously) and set up with a collider and a rigidbody2d, and we have three scripts that "do the magic". For my project, I remove the part of counting the laps because my game is not a race. Well, i set up all and everything works fine! Except for one thing: the carĀ“s rotation.
I think this is happens because the tutorial game is a topdown view but cars go from left to right, and in my game is topdown also but cars go from down to up. So the cars's sprites in my project are in topdown view and looking to up, and the car's sprite of the github project are topdown view looking to right(i wanted upload the images but appears me that i cant do it due my reputation, sorry).
Definitely, the AI works really good and the car follow without problems the path, but with a wrong rotation, like this: aicar_rotation
I tried changing things in the AICarMovement scripts related to the vectors, and angles, but without luck, so if anyone can look and give me a hand, I'll be grateful. If anyone wants more details for understand the problem, let me know. I try upload more things like pictures or gifs to show the problem, but i cant do it due the reputation.
This is the part of code in AICarMovement that i think i have to change:
public class AICarMovement : MonoBehaviour {
public float acceleration = 0.5f;
public float braking = 0.3f;
public float steering = 4.0f;
private Rigidbody2D rigidb;
Vector3 target;
void Start() {
rigidb = GetComponent<Rigidbody2D>();
}
public void OnNextTrigger(TrackLapTrigger next){
target = Vector3.Lerp(next.transform.position - next.transform.right, next.transform.position + next.transform.right, Random.value);
}
void steerTowardsTarget() {
Vector2 towarNextTrigger = target - transform.position;
float targetRot = Vector2.Angle(Vector2.right, towarNextTrigger);
if(towarNextTrigger.y < 0.0f) {
targetRot = -targetRot;
}
float rot = Mathf.MoveTowardsAngle(transform.localEulerAngles.z, targetRot, steering);
transform.eulerAngles = new Vector3(0.0f, 0.0f, rot);
}
void FixedUpdate(){
steerTowardsTarget();
float velocity = rigidb.velocity.magnitude;
velocity += acceleration;
rigidb.velocity = transform.right * velocity;
rigidb.angularVelocity = 0.0f;
}
}
Sorry about my english, is not my native language.
Turn your sprite and also the spawn game object. This way you have no fancy behaviour and all looks correct.
In steerTowardsTarget(), 2nd line:
Try to change the first parameter of Angle() from Vector2.right to Vector2.up.
Working on a multiplayer game in Unity3D. Like many others, I've got some serious issues getting the camera to follow the player. In a normal game, you simply make the camera object a child of the player object to make it follow the player. In multiplayer, this is not an option as players need to spawn (prefab).
So instead you need to use C# to make the camera follow the player using the player objects transform position. This is what I've tried:
public Transform target;
public float smoothing = 5f;
Vector3 offset;
public GameObject playerPrefab;
private void SpawnPlayer()
{
Network.Instantiate(playerPrefab, Vector3.up * 5, Quaternion.identity, 0);
offset = transform.position - target.position;
}
void LateUpdate()
{
Vector3 targetCamPos = target.position + offset;
transform.position = Vector3.Lerp(transform.position, targetCamPos, smoothing * Time.deltaTime);
}
Ofcourse I've assigned the player prefab to target. So when the game starts, the cameras position is transformed to the players position. But after that, it refuses to follow the player. It just sits there.
So I've started debugging this with:
Debug.log(target.position);
It returns the starting location of the player, but doesn't get updated as the player moves around. It remains the same. So that's obviously the reason the camera won't follow the player.
The question is: Why doesn't the player position get updated? Or most likely it does, but the script doesn't see it. What am I doing wrong?
According to your comments,here is your problem.
When you drag the prefab you assign the transform of the prefab. The player is actually an instance of the prefab (a clone) but not the prefab itself.
You need to create the new object and assign its transform to it.
GameObject player = (GameObject)Network.Instantiate(playerPrefab, Vector3.up * 5, Quaternion.identity, 0);
target = player.transform;
offset = transform.position - target.position;
First, I'd like to apologize because this is a very basic and repetitive question, but I am completely new to game development.
I understand that I can find a distance between two objects using:
float dist = Vector3.Distance(other.position, transform.position);
However, how can I find the distance between a point of one object to other object?
For instance let's say my object is this sphere
Now, how can I return an array that says that there are no objects to the left (null), in the front there is an object at 1, and to the right there is an object at 0.5?
Thank you for your patience and understanding
I'm not exactly sure what you wan't to achieve...
If you wan't to get potential objects at 0.5, 1, 1.5, etc. on lets say the Z Axis you probably would want to do this with raycasting.
If you wish to check for any objects returning the direction dependant to the Z Axis (0.5, 0.856, 1.45, etc) in contrast, you probably would either
use a scaled sphere collider and add the colliding object with the OnCollisionEnter Callback to the array/List
iterate through every object of the scene and check it's relative pos
Use Raycast Probes procedurally (using a density float and Raycasting every density offset on the Z Axis and checking if the ray hit anything ...)
...
Totally dependant on your case of use, and whether you use 2D or 3D.
Seneral
EDIT: Here's what you would want in 2D to get a wall withing range maxRange on the layer optionalWallLayer in direction y 1 (up in unity 2D)
float maxRange = 10.0f;
RaycastHit hit;
Vector3 dir = transform.TransformDirection(new Vector3 (0, 1, 0));
if (Physics.Raycast(transform.position, dir, maxRange, out hit, LayerMask optionalWallLayer))
{
Debug.Log ("Wall infront of this object in Range" + hit.distance);
// hit contains every information you need about the hit
// Look into the docs for more information on these
}
This would likely go into the Update Function of your Sphere's MonoBehaviour.
The option with the Sphere collider is useful if you are not sure if you are going to hit your obstacles. If these are small, you would likely want to add the said Sphere Collider as a component to your sphere, scale it up to your maximum distance, and add a MonoBehaviour script to the sphere, which would contain something like this:
public List<Transform> allObjectsInRange; // GameObjects to enclose into calculations, basically all which ever entered the sphere collider.
public List<float> relatedDistances;
void Update () {
// basic loop to iterate through each object in range to update it's distance in the Lists IF YOU NEED...
for (int cnt = 0; cnt < allObjectsInRange.Count; cnt++) {
relatedDistances[cnt] = Vector2.Distance (transform.position, allObjectsInRange[cnt].position);
}
}
// Add new entered Colliders (Walls, entities, .. all Objects with a collider on the same layer) to the watched ones
void OnCollisionEnter (Collision col) {
allObjectsInRange.Add (col.collider.transform);
relatedDistances.Add (Vector2.Distance (transform.position, col.collider.transform));
}
// And remove them if they are no longer in reasonable range
void OnCollisionExit (Collision col) {
if (allObjectsInRange.Contains (col.collider.transform)) {
relatedDistances.RemoveAt (allObjectsInRange.IndexOf (col.collider.transform));
allObjectsInRange.Remove (col.collider.transform);
}
}
That should do it, either of the options, based on your exact case, again:) Note both are pseudo-codes... Hope it helps!