I am making a small 2d click'n'point in Unity, and what I want to do is: I want to move towards the door and when my Player steps on a game Object with an attached SceneSwitcher Script he shall go through the door, into another scene. That works fine so far. Now I don't want him to appear in the middle of the room, but on the door, where he entered the room.
using UnityEngine;
using System.Collections;
using PixelCrushers.DialogueSystem;
public class ScenSwitcher : MonoBehaviour {
public string SceneName = "";
void OnTriggerEnter2D(Collider2D other) {
SwitchScene();
}
void SwitchScene(){
LevelManager levelManager = DialogueManager.Instance.GetComponent<LevelManager>();
levelManager.LoadLevel (SceneName);
changePosition ();
Debug.Log ("Scene Wechseln nach: " + SceneName);
}
void changePosition(){
GameObject player = GameObject.Find("Player");
player.transform.position = new Vector3(12,12,0);
}
}
That is my code, it does change Scenes, but not change the position. I would appreciate any help :)
On your ChangePosition() method you are passing hardcoded values to player position and it will assume always (12,12,0) on your scene space.
You need to define a spawn manager where you will get dynamically witch spawn point in your scene you want to use.
edited:
1: Try to create a singleton GameManager ( you can find singleton pattern examples here ) (IMPORTANT: Add DontDestroyOnLoad on your GameManager Awake).
2: In your GameManager define a Vector3 NextPosition property or something like this.
3: Declare a public Vector3 Destination on your "teleport" script to set it per teleport on inspector/editor.
4: Before this line levelManager.LoadLevel (SceneName) of code set GameManager.NextPosition = this.Destination;
5: If you are not persisting your character between scenes just call on one of hes behaviours Awake() or, if he persists create a method void OnLevelWasLoaded(int level) and chage players position setting GameManager.NextPosition ( wisely testing if it is valid for the current level before ;) ).
I cant try or do better coding now because I don't have access to unity editor so I hope it helps at last start a good research to solve your problem =/.
I would think the loadLevel function destroys the current script so changePosition does not get executed? I could be wrong.
Even if it is getting executed, there is a good chance it is executed before the level load and the properties for the next scene override where it got moved to.
I forget the exact syntax but look into getting GameObjects to not be destroyed on scene change.
EDIT
Object.DontDestroyOnLoad
Related
If that is not possible, can I at least find it using raytracing?
I want to make some enemy GameObjects (which are instantiated from a prefab, which spawn randomly) always look towards the player.
I don't think I can just call it's xyz coordinates, but maybe I can find them using raytracing? How exactly do I do that? Even if I know what raytracing is and used it before in other non-unity projects, I have no idea how to implement it in unity.
Your enemies should be able to get reference to player somehow (probably Singleton for entry level, or Dependency Injection for pros) and use player.transform.position
So basically your player should look like that:
public class Player : MonoBehaviour
{
public static Player Instance;
void Awake()
{
Instance = this;
}
}
And then enemy can use:
Player.Instance.transform.position
to get players position.
As the title suggests, I've literally just started learning Unity recently and I'm practising by making a side scrolling shooter. I've been following a Udemy course about it and (to my knowledge) I've been following the tutor's instructions to the letter, but at the point where he tests his and it works fine, by projectiles go straight through my enemies.
I'm a bit stumped at this point and so I thought I'd post here to see what you guys thought. I bet it's something really simple I've not done.
Please see my projectile code below:
using UnityEngine; using System.Collections;
public class DestroyEnemyAndProjectile : MonoBehaviour {
public GameObject WhiteExplosion;
public GameObject OrangeExplosion;
void Start()
{
}
void Update()
{
}
void OnCollisionEnter2D (Collision2D tempCollision)
{
if (tempCollision.gameObject.tag == "Collision")
{
spawnParticles(tempCollision.transform.position);
Destroy(tempCollision.gameObject);
}
}
void spawnParticles(Vector2 tempPosition)
{
Instantiate(WhiteExplosion, tempPosition, Quaternion.identity);
Instantiate(OrangeExplosion, tempPosition, Quaternion.identity);
}
}
Thanks for your help!
I did post a question to them which got a response, they suggested that perhaps the projectile is going too fast and check there was a Rigidbody 2D attached - both of which were already collect
make sure that the object you're colliding with has the tag "Collision", with the same capitalisation.
If it's not, you can do this by:
1. Selecting the GameObject to be collided with
2. In the top-right, select the Tag property
3. Add tag, click the plus and type in "Collision"
4. Select the GameObject again, and select the "Collision" tag from the Tag property dropdown
Otherwise, if that's not the issue. Make sure the projectile has a type of Collider2D component, and that the projectile, or the object being collided with, has a Rigidbody2D.
First I would like to know what the behaviour of this script curently is. Is the collision method being called, and the projectile goes through the enemy anyway? Or the collision method is not being called at all?
That being said, these are things that you should check in order for collision to work:
Make sure that the projectile and the enemy have Collider2D components attached to them.
Make sure that the projectile and/or the enemy (at least one of them must) have a Rigidbody2D attached to it.
Make sure that the layer of the projectiles and the layer of the enemies are set to collide in the collision matrix (You can find the collision matrix in Edit->ProjectSettings->Physics)
Make sure that the enemy GameObject has its tag set to "Collision".
P.S: Welcome to Unity where issues like this are, in fact, usually caused by something super simple that you probably missed.
I have the following code:
public Rigidbody2D ball;
Vector2 sp = new Vector2(0f, 2.1f);
void Update() {
if (Input.GetKeyDown("w")) {
SpawnBall();
DestroyBall();
}
}
void SpawnBall()
{
Instantiate(ball, sp, transform.rotation);
}
void DestroyBall()
{
if (ball.transform.position.y >= -5.7f)
{
Destroy(ball);
}
}
and the code is supposed to generate a new ball every time when "w" is pressed, but for some reason it creates multiple clones and it crashes the engine. How can I create a single clone only?
And also the destroy method doesn't do anything, although it should remove the clone when it passes -5.7 on the y-axis.
Thanks in advance
Create a new script named "SpawnRigidbody" and copy and paste the below code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnRigidbody : MonoBehaviour
{
public Rigidbody2D ball;
Vector2 sp = new Vector2(0f, 2.1f);
void Update()
{
if (Input.GetKeyDown("w")) {
SpawnBall();
}
}
void SpawnBall()
{
Debug.Log ("spawn");
GameObject go = Instantiate(ball, sp, transform.rotation).gameObject;
go.AddComponent<DestroyAfterPosition> ();
}
}
Now create another script named "DestroyAfterPosition" and copy and paste the below code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyAfterPosition : MonoBehaviour
{
void Update ()
{
if (transform.position.y <= -5.7f)
{
Destroy(gameObject);
}
}
}
Create an empty game object and attach the SpawnRigidbody and then assign your ball in the inspector.
Hope this help you.
There are a couple problems with your Destroy() statement. First, it is destroying ball which is the Rigidbody2D. You will instead want to destroy the gameobject attached to the ball:
Destroy(ball.gameObject);
Second, you are trying to destroy the ball immediately after it is created, but only if y>=-5.7f. I think instead what you are looking to do is continuously check if the ball is above that point and destroy it if it is. Since you are creating multiple balls, they will all need their own check, which means you need to create a script for the ball prefab and in the Update() check its position and Destroy(gameObject) as necessary.
I think you may want to declare ball as a GameObject at the beginning of your script as well, so you are instantiating a gameobject and not just a Rigidbody2D:
public GameObject ball;
Object.Instantiate creates a clone of the provided object, so each time it is called a new object is created. MonoBehaviour.Update is called every frame, which means it's called at least 30 times per second (usually 60 or more on a PC).
So 30+ times per second, your code checks if the w key is held down, and, if so:
A clone of ball is created
Destroy the original ball if it is beyond -5.7 on the y-axis.
Thus, you're creating 30+ ball clones per second, and none will be deleted (because the DestroyBall method only looks at the original ball, not the clones).
If you want to work with the cloned object, assign the result of Instantiate to a field:
ballClone = Instantiate(ball, sp, transform.rotation);
Then you can check if ballClone exists and skip the SpawnBall call if the clone already exists. You can also use ballClone in the DestroyBall method.
ryemoss' answer seems like it's
also important. This answer is just based on looking at your code and the public Unity docs; I don't have a lot of experience with Unity.
Your destroy call is being called once, and only immediately after creating the object.
So it's currently doing this...
User clicks button...
Create ball...
Check to see if the ball is a certain height. It's not, so ignore...
Ball drops down based on gravity or whatever force compels it.
... and is never deleted.
If you want the ball to be destroyed when it reaches a certain point, either...
Have SpawnBall return the game object, which you store and check / delete later in Update,
...or...
Create a script that just checks the object's transform.position and blows up if it's where it needs to be. Attach that to the prefab of the ball you're creating a duplicate of.
I'm fairly new to C#(basically first time using, having to script for this project), I'm trying to teleport (from off screen to on) an object in my game(i'm using a cube for a simple object, in which I will use inkscape to create a 'better' object in its place when it works)will add cube2 later, just focusing on getting this working.
The aim is to teleport an object to where to my 'Bumber' prefab (the floor), based upon the player clicking a position on the 'Bumber' and spawn where the mouse position was on that 'Bumber' and if not on the 'Bumber' don't spawn at all(haven't go to bumber check yet), which will trigger an event, causing the player to lose.
When I was playing the game before, when I clicked, the cube would only despawn and then throw an error at me and not spawn in at the cursors position
I have my 'cube' prefab (dragged from hierarchy into Resources folder, which has the spawn script component). When I go back into unity, I get the error:
(32, 37) the name 'cube' doesn't exist in current context
(32,25) The best overloaded method match for `UnityEngine.Object.Instantiate(UnityEngine.Object, UnityEngine.Vector3, UnityEngine.Quaternion)' has some invalid arguments
(32, 25) Argument #1' cannot convertobject' expression to type `UnityEngine.Object'
I've tried for hours to fix this script, looking at unity database and to no avail.
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour {
public int trapCount;
void Start ()
{
trapCount = 0;
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
}
void Update ()
{
if (Input.GetMouseButtonDown (0))
{
Spawner ();
trapCount++;
}
}
void Spawner()
{
Vector3 mousePosition = Input.mousePosition;
transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(trapCount == 0)
{
Instantiate(cube, transform.position, Quaternion.identity); //getting error here, I don't care about rotation value, don't want to rotate at all, but doesn't like it, if it doesn't have anything there.
}
else if (trapCount >= 1)
{
Debug.Log("Trap limit reached!");
}
}
}
C# please, also, if you could, explain what you're doing, thank you kindly!
Always (well, almost always) believe what the error messages tell you.
(32, 37) the name 'cube' doesn't exist in current context
You get this for the line
Instantiate(cube, transform.position, Quaternion.identity);
At that point there is no cube anywhere within the scope of the method. You have your
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
in your Start() method, but it only exist within that method. It's not a member of the class for example. Making it a member would solve that problem.
And that is more than likely also the cause of the subsequent errors. If it doesn't know what a cube is, it has no idea what to do with it as an argument of Instantiate().
If you're entirely new to C# the biggest favour you could do yourself is to pick up a good book. Unity will allow you to get pretty far by hacking away at it, but there will be a point where there's simply no substitute for learning the language. It will help you tremendously.
Good luck.
So I am developing a simple C# program that allows you to move around a graphic and have it fire bullets that travel from the player to the position of the mouse at the time of the mouse click. I'm still new to C# but have some experience with Java and Python.
I am fully able to move my character with the WASD but unable to get the bullets to be drawn let alone get them to move as they update.
Where might the bug be?
The projectile object's draw method?
The Game1 class's update method for the user input?
The projectile's object's direction setting?
Here is the full code:
http://pastebin.com/j5QVLKU3
I left the player class out, but it has nothing more then a few player variables like health.
For start, could you move
mouseStateCurrent = Mouse.GetState();
if (mouseStateCurrent.LeftButton == ButtonState.Pressed)
{
if (mouseStatePrevious.LeftButton != ButtonState.Pressed)
{
AddProjectile(player.positionPlayer);
mouseStatePrevious = mouseStateCurrent; //<-- This line
}
}
//<-- Here
Once you press your button, you're never gonna enter that if again.
Edit 1
Furthermore, this in your Projectile
Player playerObject = new Player();
Game1 gameObject = new Game1();
has to look like:
Player playerObject;
Game1 gameObject;
public Projectile(Player player, Game1 game)
{
playerObject = player;
gameObject = game;
}
Since you're using those only to get the origin and destination for the bullet, it would be better if you just calculated those outside, and passed them with the initialize. (because it would remove Projectile's need to know what Game1 and Player objects looked like)
You could also completely remove the Initialize method and just use Projectile's constructor, that seems more natural. (if you use the constructor for this, then you know that any time you have an instance, you can use it without having to call additional methods)
Slight edit
I don't think you really need the bulletOrigin in your Projectile class, you could just use the position, and move it from there to the bulletDestination.
Also, Vector2 class is made with operator overloaded methods, so you could use
positionBullet += directionLine*velocity;
instead of
positionBullet = Vector2.Add(positionBullet, directionLine * velocity);
Other than those, your code seems fine! Tell me if it still doesn't work after these changes. Also, use your debugger to step into it, see if you can find anything interesting. :)