A few days ago I started Unity and I used the official tutorials to learn. I've got the first game going and i'm starting to love programming. I'm very new to this and tought it would help me if I made these tutorial games better. Everything went great, but now i'm stuck. I want a menu that appears when I win the game. I made the menu and it has 3 buttons ('Try again', 'Menu' and 'Exit'). Here is a picture: http://prntscr.com/9jy71h . The buttons work, but my only problem is that they appear there the whole game long, while I only want them at the end. I tried a lot, but i seem to get this error all the time: 'Retry' doesn't exist in the current context.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed;
public Text countText;
public Text winText;
private Rigidbody rb;
private int count;
void Start ()
// The game starts here.
{
rb = GetComponent<Rigidbody>();
count = 0;
SetCountText ();
winText.text = "";
Retry.GameObject.SetActive(false);
Menu.GameObject.SetActive(false);
Exit.GameObject.SetActive(false);
}
void FixedUpdate ()
// Movement.
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rb.AddForce (movement * speed);
}
void OnTriggerEnter(Collider other)
// Picking things up and count score.
{
if (other.gameObject.CompareTag("Pick Up"))
{
other.gameObject.SetActive (false);
count = count + 1;
SetCountText ();
}
}
void SetCountText ()
{
countText.text = "Count:" + count.ToString ();
if (count >= 12)
// End of the game, you won.
{
winText.text = "You win!";
Retry.GameObject.SetActive(true);
Menu.GameObject.SetActive(true);
Exit.GameObject.SetActive(true);
}
}
}
Why can't he recognize my gameObject that I made? (the buttons you saw at the picture) Sorry for my bad english and thank you for taking the time to read this and if possible answer.
EDIT: http://prntscr.com/9jybke These are all the errors. If I however, delete the 6 gameobjective(bool) lines on the top and bottom it works fine, but I have the menu ON all the time.
What you are missing is references from your script to the button game objects, so that you can turn them on/off.
If you add to your script
public GameObject retryButton;
And similarly for the other buttons, and then in Unity in the inspector for your script you drag the three button GameObjects to their corresponding "slots" in the inspector.
Then in your code you replace Retry.GameObject.SetActive() with retryButton.SetActive()
And likewise for the other buttons.
Actually, it seems you are already doing this for your "countText" and "winText".
try to put the button inside a game object and use object .SetActive(false)
it worked for me.
Related
As you can see in the screenshoot I can't see prefabs in the game tab but only in the editor. I have made a simple function for shooting(not finished yet), it works fine, it spawns the prefabs but i can't see them in the game tab, I have already tried changing the Sorting Layer, move the camera, change Z position but nothing appen.
This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttack : MonoBehaviour
{
[SerializeField]
float delayBetweenShots = 0.4f;
float timePassedSinceLast = 0f;
// Start is called before the first frame update
void Start()
{
timePassedSinceLast = delayBetweenShots;
}
// Update is called once per frame
void Update()
{
Aiming();
Shooting();
}
void Aiming()
{
var objectPos = Camera.main.WorldToScreenPoint(transform.position);
var dir = Input.mousePosition - objectPos;
transform.rotation = Quaternion.Euler(new Vector3(0,0,Mathf.Atan2(-dir.x, dir.y) * Mathf.Rad2Deg));
}
void Shooting()
{
if(Input.GetMouseButton(0) && timePassedSinceLast >= delayBetweenShots)
{
GameObject bullet = (GameObject)Instantiate(Resources.Load("bullet"), transform.position, transform.rotation);
timePassedSinceLast = 0f;
}
else
{
timePassedSinceLast += Time.deltaTime;
}
}
}
The prefabs get instantiated correctly. As others suggested as well, the best way to find "lost" objects in your game is to shoot some stuff, pause the game, go into scene view, turn on 3D mode and double click one of the prefabs in the hierarchy. The camera will take you straight to your object.
I am not new to programming, but I am new to C#. I am experienced in Python, Java, and HTML. My game is 2D I have a game where my character currently has to touch the enemy to kill it. Now I added code for shooting a bullet to kill the enemy. I also want the bullet to be shot if the spacebar is pressed. The character is supposed to a shoot bullet in either direction. I have taken my code from an example my professor gave me which was originally Javascript and I converted it to C#. Unity no longer supports Javascript. The example code he gave me was basically a rocket shooting as many bullets as I clicked (clicking the mouse shoots bullets) to eliminate an enemy, however the rocket in that example does not move. In my game, the character moves, so the bullet has to get the position of the character. What is the correct code for getting the character position and shooting a bullet correctly?
I tested my game with my current code. The bullet is being spit out of nowhere (from the bottom of my background wallpaper [smack in the middle of the bottom] to a little below the wallpaper). Not even from the character...
Also, I added the Hit class script to my Bullet category in Unity.
Complete Camera Controller (no issues here at all)
using UnityEngine;
using System.Collections;
public class CompleteCameraController : MonoBehaviour {
public GameObject player; //Public variable to store a reference to the player game object
private Vector3 offset; //Private variable to store the offset distance between the player and camera
// Use this for initialization
void Start ()
{
//Calculate and store the offset value by getting the distance between the player's position and camera's position.
offset = transform.position - player.transform.position;
}
// LateUpdate is called after Update each frame
void LateUpdate ()
{
// Set the position of the camera's transform to be the same as the player's, but offset by the calculated offset distance.
transform.position = player.transform.position + offset;
}
}
Complete Player Control Class (If you read the comments in the code that say the "BULLET CODE", that's new code I have placed in the game for the bullets.
using UnityEngine;
using System.Collections;
//Adding this allows us to access members of the UI namespace including Text.
using UnityEngine.UI;
public class CompletePlayerController : MonoBehaviour
{
public float speed; //Floating point variable to store the player's movement speed.
public Text countText; //Store a reference to the UI Text component which will display the number of pickups collected.
public Text winText; //Store a reference to the UI Text component which will display the 'You win' message.
private Rigidbody2D rb2d; //Store a reference to the Rigidbody2D component required to use 2D Physics.
private int count; //Integer to store the number of pickups collected so far.
Rigidbody2D bullet;
float speed2 = 30f; //BULLET CODE
// Use this for initialization
void Start()
{
//Get and store a reference to the Rigidbody2D component so that we can access it.
rb2d = GetComponent<Rigidbody2D> ();
//Initialize count to zero.
count = 0;
//Initialze winText to a blank string since we haven't won yet at beginning.
winText.text = "";
//Call our SetCountText function which will update the text with the current value for count.
SetCountText ();
}
//FixedUpdate is called at a fixed interval and is independent of frame rate. Put physics code here.
void FixedUpdate()
{
//Store the current horizontal input in the float moveHorizontal.
float moveHorizontal = Input.GetAxis ("Horizontal");
//Store the current vertical input in the float moveVertical.
float moveVertical = Input.GetAxis ("Vertical");
Rigidbody2D bulletInstance; //BULLET CODE
//Use the two store floats to create a new Vector2 variable movement.
Vector2 movement = new Vector2 (moveHorizontal, moveVertical);
//Call the AddForce function of our Rigidbody2D rb2d supplying movement multiplied by speed to move our player.
rb2d.AddForce (movement * speed);
if(Input.GetKeyDown(KeyCode.Space)&& Hit.hit == false) //BULLET CODE IN HERE
{
// ... instantiate the bullet facing right and set it's velocity to the right.
bulletInstance = Instantiate(bullet, transform.position, Quaternion.Euler(new Vector3(0,0,0)));
bulletInstance.velocity = new Vector2(speed2, 0);
bulletInstance.name = "Bullet";
}
}
//OnTriggerEnter2D is called whenever this object overlaps with a trigger collider.
void OnTriggerEnter2D(Collider2D other)
{
//Check the provided Collider2D parameter other to see if it is tagged "PickUp", if it is...
if (other.gameObject.CompareTag ("PickUp"))
{
//... then set the other object we just collided with to inactive.
other.gameObject.SetActive(false);
transform.localScale += new Vector3(0.1f, 0.1f, 0);
//Add one to the current value of our count variable.
count = count + 1;
//Update the currently displayed count by calling the SetCountText function.
SetCountText ();
}
}
//This function updates the text displaying the number of objects we've collected and displays our victory message if we've collected all of them.
void SetCountText()
{
//Set the text property of our our countText object to "Count: " followed by the number stored in our count variable.
countText.text = "Count: " + count.ToString ();
//Check if we've collected all 12 pickups. If we have...
if (count >= 12)
//... then set the text property of our winText object to "You win!"
winText.text = "You win!";
}
}
Hit code. All code in this class is made for the bullet.
using UnityEngine;
using System.Collections;
public class Hit : MonoBehaviour
{
GameObject[] gameObjects;
public static bool hit = false;
void Removal ()
{
gameObjects = GameObject.FindGameObjectsWithTag("Bullet");
for(var i= 0 ; i < gameObjects.Length ; i ++)
Destroy(gameObjects[i]);
}
void OnCollisionEnter2D ( Collision2D other )
{
if(other.gameObject.name=="Bullet")
{
Removal();
Destroy(gameObject);
hit = true;
}
}
}
I see several issues with the code you wrote. as #Kyle Delaney suggested, I'd also highly recommend you check out the Unity Learn website, and go through several tutorials before moving through. I've highlighted a few issues below that may help solve your problem, but you could really benefit from changing your approach in the first place to avoid many of these issues. See below.
In your camera controller class, why not make the offset public so you can set it yourself in the inspector>
In Player controller class:
changed:
if (Input.GetKeyDown(KeyCode.Space)) //Shoot bullet
{
// ... instantiate the bullet facing right and set it's velocity to the right.
Rigidbody2D bulletRB = Instantiate(bullet, transform.position, transform.rotation);
bulletRB.AddForce(new Vector2(speed2,0), ForceMode2D.Impulse);
}
On a click, this instantiates the bullet prefab and sets its transform to copy the position and rotation of the player. It then adds a force to it to the right. You should avoid setting the velocity manually with rigidbodies, this can cause unwanted behaviour. Use the Addforce/addTorque methods instead. The ForceMode says to ignore its mass and set its velocity.
Then delete your Hit class, and replace with this Bullet class, which you drag onto the bullet prefab. Your player shouldn't be in charge of checking for bullet hits. that's the bullet's job. The player just launches the bullets and then the bullets do what bullets do. this just checks to see if the bullet hit anything, if so it destroys it. You can make this more complicated if you want. I would recommend using layers to determine which layers the bullet checks collisions with. You probably don't want bullets destroying your terrain. and you definitely don't want bullets destroying the player itself!
public class Bullet : MonoBehaviour
{
private void OnCollisionEnter2D(Collision2D collision)
{
Destroy(collision.gameObject);
Destroy(this.gameObject);
}
}
Also you shouldn't need to set the name of the bullet, since your prefab bullet should already be named "bullet".
I hope this gets you started in the right direction. But based on your code, I HIGHLY recommend you work through the tutorials before continuing with any projects. The unity staff that make them are super helpful and the tutorials start off really simple but get really complicated fast, so you actually come away learning a ton!
Perhaps the problem has to do with the player's parent transform. You could try something like this to make sure the bullet has the right parent:
bulletInstance = Instantiate(bullet);
bulletInstance.transform.parent = transform.parent;
bulletInstance.transform.position = transform.position;
bulletInstance.velocity = new Vector2(speed2, 0);
bulletInstance.name = "Bullet";
If that doesn't work it may be worthwhile to check the player's Rect Transform to see where the anchors and pivot are. Perhaps the player's actual "position" coordinates aren't where you think they are.
Have you done the Space Shooter tutorial? It has a segment about shooting bullets.
So I'm currently starting with programming, and I'm fresh to this topic.
I did start with the Unity game engine; people say it's not the best way to start but whatever.
I made the first game with the basic tutorial of unity.
Tho I can't yet really understand the complexity of C#.
(Using Visual Studio, not sure if I should switch to sublime and how)
This game is about moving a ball around and collecting stuff.
On the PC, it works just fine with the AddForce and Vector3 movement on the arrow keys. Though I wanted to try making this game for a mobile device, I thought about instead of typing the screen I might use the gyroscope of the mobile device. I found the "gyro" variable(?) in the Unity API documentation, but I don't really know how I define it just to move x and z-axis, so the ball won't starts flying off the table. I tried with the accelerator variable(?), but exactly this happened, even tho y-axis was set to 0.
The following code is what i have at GameObject "player" so far:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class AccelerometerInput : MonoBehaviour
{
public float speed;
public Text countText;
public Text winText;
private Rigidbody rb;
private int count;
void Start()
{
rb = GetComponent<Rigidbody>();
count = 0;
SetCountText();
winText.text = "";
}
private void Update()
{
transform.Translate(Input.gyro.x, 0, -Input.gyro.z);
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Capsule"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Count: " + count.ToString();
if (count >= 8)
{
winText.text = "You Win";
}
}
}
I'm new to all of this, especially coding, anything that helps me understand how the language is interpreted will be much appreciated!
Thank you!
I did start with the Unity game engine, people say it's not the best
way to start but whatever.
That's right. There are many C# tutorials online. Just understand basic C# stuff and you should be fine in Unity. If you don't do this, there will be limitation on things you can do with Unity.
To answer your question, you need the accelerometer not the gyro sensor. Also, remove transform.Translate(Input.gyro.x, 0, -Input.gyro.z); from the Update function. Do not move Objects with Rigidbody via transform.Translate or else, you will run into issues such as no collision.
Something like this should do it:
Vector3 movement = new Vector3(-Input.acceleration.y, 0f, Input.acceleration.x);
You still need a way to detect if you are building for mobile devices or desktop. This can be done with Unity's preprocessor directives.
void FixedUpdate()
{
Vector3 movement = Vector3.zero;
//Mobile Devices
#if UNITY_IOS || UNITY_ANDROID || UNITY_WSA_10_0
movement = new Vector3(-Input.acceleration.y, 0.0f, Input.acceleration.x);
#else
//Desktop
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
movement = new Vector3(moveHorizontal, 0f, moveVertical);
#endif
rb.AddForce(movement * speed);
}
I am having problems getting OnCollisionEnter2d. I am just starting out with Unity and thought I could throw together a simple version of pong just to get started with the basics. In a script I have attached to a ball I have an OnCollisionEnter2d method but it is not being called.
After looking at other posts where people had this problem I have unchecked "Is Kinematic" and set gravity to 0. After unchecking "Is Kinematic" I had to check the x, y and z constraints on the back wall to stop it getting knocked away by the ball. The ball has a "circle collider 2d" component and the wall has a "Box Collider 2d" one. They both have non Kinematic RigidBody2d components. Another answer to a similar question said to check if collisions between different layers was enabled. They are both on the same layer.
I'm sure I have just missed something simple but I am really stumped. This was meant to just be something quick that I threw together before desigining something a little bit meatier. :) If someone could help me out I would really appreciate it. Code and components below:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class BallController : MonoBehaviour {
public float speed;
public Text scoreText;
private int score;
// Use this for initialization
void Start () {
Rigidbody2D rb2d = GetComponent<Rigidbody2D>();
Vector2 movement = new Vector2(1, 1);
rb2d.AddForce(movement * speed);
score = 0;
scoreText.text = "Score: " + score.ToString();
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter2d (Collider2D other)
{
scoreText.text = "test"; // added this line just to see if the method was being called at all
if (other.gameObject.tag == "BackWall")
{
score = score + 1;
scoreText.text = "Score: " + score.ToString();
}
}
}
Ball and back wall components
Sorry I can't paste images inline yet as I don't have the rep.
The correct syntax is OnCollisionEnter2D(Collision2D collision)
You put OnCollisionEnter2d(Collider2D other)
Unity will not recognize a function if it is misspelled even slightly.
(You would not believe how many times I myself fell prey to this.)
Relevant Link: http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnCollisionEnter2D.html
I'm creating a game in unity 2D and in this game a GameObject called Moving_Truck is required to smoothly move into the scene from that left side. as this will be required later, I tried to make the method run from an other code on another object, the object is called scene control and the script is called opening scene.
the problem is when I push the space button the Moving_Truck game object does not move. I am fairly new to C# and have tried a few solutions such as Vector2.MoveTowards and Vector2.Lerp. I have also modified my code multiple times trying to get this to work. here is the most recent version of the codes:
CharacterBase
using UnityEngine;
using System.Collections;
public class CharacterBase : MonoBehaviour {
private float SprSize, HalfSprSize, Distance;
public int run = 1;
public void CharMove(int Dir, string Char, float speed, string BackgroundName)
{
var CharOBJ = GameObject.Find(Char);
var BGOBJ = GameObject.Find(BackgroundName);
SprSize = CharOBJ.GetComponent<Renderer>().bounds.size.x;
HalfSprSize = SprSize / 2;
Vector2 EndPos = new Vector2(BGOBJ.transform.position.x, CharOBJ.transform.position.y);
Debug.Log(EndPos);
CharOBJ.transform.position = Vector2.MoveTowards(CharOBJ.transform.position, EndPos, speed * Time.deltaTime);
}
}
OpeningScene
using UnityEngine;
using System.Collections;
public class OpeningScene : CharacterBase {
int Advance = 0, Run = 0;
void Start ()
{
}
void FixedUpdate()
{
if (Input.GetKeyUp("space"))
{
Run = 1;
Debug.Log("Space Pressed");
}
if (Run == 1)
{
Run = 0;
Advance += 1;
switch (Advance)
{
case 1:
CharMove(-1, "Moving_Truck", 0.05f, "House_Front");
break;
case 2:
CharMove(1, "Moving_Truck", 0.05f, "House_Front");
break;
}
}
}
}
This is driving me nuts, I've been trying to fix it for about an hour or Two now, can someone please help, also sorry for the long question, just comment if you need more info. also please ignore the Dir Argument for now.
Thanks.
Unity's Input.GetKeyUp only returns true on the frame when you release the spacebar. Because of this, CharMove will only be called that one frame you press the spacebar, and then only move 0.05f * timeDelta, which is probably going to be less than a pixel.
Also, this is unrelated, but you don't want to call GameObject.Find(string) every time you move the character. Instead, call it once in the Start() method and then store the result to a field.
Have you tried
GetComponent<Rigidbody2D> ().velocity = new Vector2 (moveSpeed, GetComponent<Rigidbody2D> ().velocity.y);