How do I add a restart function to a game in Unity? - c#

I have followed and completed a Unity tutorial however once the tutorial is said and done, there was no function mentioned to restart the game.
Other than closing the application and re-opening, how would I go about adding something like this in?

There are do ways to restart game in Unity:
1.Reset every useful variables such as position, rotation, score to their default position. When you use this method, instead of #2, you will reduce how much time it take for your game to load.
Create a UI Button then drag it to the resetButton slot in the Editor.
//Drag button from the Editor to this
public Button resetButton;
Vector3 defaultBallPos;
Quaternion defaultBallRot;
Vector3 defaultBallScale;
int score = 0;
void Start()
{
//Get the starting/default values
defaultBallPos = transform.position;
defaultBallRot = transform.rotation;
defaultBallScale = transform.localScale;
}
void OnEnable()
{
//Register Button Event
resetButton.onClick.AddListener(() => buttonCallBack());
}
private void buttonCallBack()
{
UnityEngine.Debug.Log("Clicked: " + resetButton.name);
resetGameData();
}
void resetGameData()
{
//Reset the position of the ball and set everything to the starting postion
transform.position = defaultBallPos;
transform.rotation = defaultBallRot;
transform.localScale = defaultBallScale;
//Reset other values below
}
void OnDisable()
{
//Un-Register Button Event
resetButton.onClick.RemoveAllListeners();
}
2.Call SceneManager.LoadScene("sceneName"); to load the scene again. You can call this function when Button.onClick.AddListener is called..
Create a UI Button then drag it to the resetButton slot in the Editor.
//Drag button from the Editor to this
public Button resetButton;
void OnEnable()
{
//Register Button Event
resetButton.onClick.AddListener(() => buttonCallBack());
}
private void buttonCallBack()
{
UnityEngine.Debug.Log("Clicked: " + resetButton.name);
//Get current scene name
string scene = SceneManager.GetActiveScene().name;
//Load it
SceneManager.LoadScene(scene, LoadSceneMode.Single);
}
void OnDisable()
{
//Un-Register Button Event
resetButton.onClick.RemoveAllListeners();
}
The decision to which method to use depends on how much Objects in your scene and how much time it takes your scene to load. If the scene has a huge world with baked light maps and HQ textures then go with #1.

For example you can reload main scene for restart game.
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

Related

How to change the position of GameObjects with Unity Input.GetMouseButtonDown method?

I already know how to click on 3D Objects in the scene by using the Input.GetMouseButtonDown. I'm trying to change the 3D Object position by clicking on the object. I added a Box Collider in the object and I'm calling the following method.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
foreach (GameObject child in floorTiles) {
BoxCollider box = child.GetComponentInChildren<BoxCollider>();
if (hit.transform.name.Equals(box.name))
{
handleOnMouseDown(hit.collider);
}
}
}
}
}
floorTiles is an array of GameObjects.
If I hit one of these objects the below function is called:
void handleOnMouseDown(Collider box)
{
GameObject parent = box.transform.parent.gameObject;
Vector3 position = parent.transform.position;
positionX.GetComponent<TextMeshProUGUI>().text = position.x.ToString();
posXButtonPlus.GetComponent<Button>().onClick.AddListener(() => handleOnChangePosition("posx", parent));
}
This works, however, when I click many objects, all the last objects clicked also keep changing their positions. How can I change one position per time?
Each click on an object, adds listener to your button, but you don't ever remove listeners. You end up with multiple listeners, that's why more objects are moved than intended.
You could remove listener after each button click, but that seems like a total overkill.
Instead of adding multiple listeners, consider adding just one which will remember the last clicked object, and clicking your button will move only that object.
Also, if you want to move objects just by clicking on them, not on button click, you can simplify all these, and move the object directly in handleOnMouseDown.
Remove listeners variant:
void handleOnMouseDown(Collider box)
{
posXButtonPlus.GetComponent<Button>().onClick.AddListener(() => handleOnChangePosition("posx", box.gameObject));
}
void handleOnChangePosition(string pos, GameObject go)
{
// I don't have code for moving, but I imagine looks something like this. right * 0.5f can be anything, did it just for tests.
go.transform.position += Vector3.right * 0.5f;
posXButtonPlus.GetComponent<Button>().onClick.RemoveAllListeners();
}
Last clicked variant:
GameObject lastClicked;
void Awake()
{
posXButtonPlus.GetComponent<Button>().onClick.AddListener(() => handleOnChangePosition());
}
void handleOnMouseDown(Collider box)
{
lastClicked = box.gameObject;
}
void handleOnChangePosition()
{
lastClicked.transform.position += Vector3.right * 0.5f;
}
Without buttons and other stuff:
void handleOnMouseDown(Collider box)
{
box.transform.position += Vector3.right * 0.5f;
}

Unity New Input System .started doesn't work but .performed works twice

I'm creating a shooting angry birds style game with new input system.
I want to save the mouse position to a variable when the mouse is clicked and released.
Subscribing to the .started event doesn't work. Using .performed, it works with 1 click 2 times, once at the start and once after release.
When I try .canceled it doesn't work too.
private void OnEnable()
{
controls.Gameplay.Shoot.started += _ => PlayerAimingStart();
controls.Gameplay.Shoot.performed += _ => PlayerAimingPerformed();
}
private void PlayerAimingStart()
{
shootingPositionStart = controls.Gameplay.MousePosition.ReadValue<Vector2>(); shootingPositionStart.z = 0f;
}
private void PlayerAimingPerformed()
{
shootingPositionEnd = controls.Gameplay.MousePosition.ReadValue<Vector2>(); shootingPositionEnd.z = 0f;
Vector3 force = shootingPositionStart - shootingPositionEnd;
Vector3 clampedForce = Vector3.ClampMagnitude(force, maxDrag) * power;
bulletGO.GetComponent<Rigidbody2D>().AddForce(clampedForce, ForceMode2D.Impulse);
}
In the input action asset, under my gamplay action map and action, Gameplay > Actions: Shoot/Left Button
I had to add a press interaction on the right hand side
Interactions > Press
and set the trigger behavior to Press And Release.

Disable GameObject creation when clicking on a GUI Button

I have a chunk of code similar to this:
GameObject prefab; // Gets set when GUI button is clicked
void Update(){
if(Input.GetMouseButtonUp(0) && prefab){
Instantiate(prefab, /* At mouse position on ground */);
prefab = null;
}
}
Here is the code when I click the button:
public void SetBuilding(GameObject building){
prefab = building;
Destroy(ghostBuildingObject);
ghostBuildingObject = Instantiate(building);
if (ghostBuildingObject) {
// Set the alpha to half
Color c = ghostBuildingObject.GetComponent<MeshRenderer>().material.color;
c.a = 0.5f;
ghostBuildingObject.GetComponent<MeshRenderer>().material.color = c;
// Disable Components
ghostBuildingObject.GetComponent<Collider>().isTrigger = true;
Destroy(ghostBuildingObject.GetComponent<NavMeshObstacle>());
Destroy(ghostBuildingObject.GetComponent<Building>());
ghostBuilding = ghostBuildingObject.AddComponent<GhostBuilding>();
ghostBuildingObject.layer = LayerMask.NameToLayer("Ghost");
ghostBuildingObject.name = "Ghost Building";
}
}
Basically what it does is creates an object where I click on the ground object. What happens is when I click on a button it still creates the game object. How can I stop it from creating a gameObject when I click on a GUI Button?
Was in the process of typing this before you put your own answer. I still decided to put my answer because what you did in your answer is so wrong and unnecessary. You are allocating memory multiple times per frame, in the code in your answer only to detect a click...
I am using a Button (UnityEngine.GUI.Button)
I am using the unity5 GUI elements
You shouldn't be using that to begin with. Some people suggests you should use a raycast but the problem of a ray passing through a UI will still remain.
What you need is the a Button from UnityEngine.UI.Button not UnityEngine.GUI.Button. You have to change your whole program to use UI from UnityEngine.UI.
To create your button, you go to GameObject->UI->Button. That should create Canvas and other components required to get Button to work. Here are Unity UI tutorials.
Basically what it does is creates an object where I click on the
ground object.
You can detect a button click by implementing IPointerClickHandler and overriding the OnPointerClick function.
Attach the script below to the ground you want to detect the click.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Click : MonoBehaviour, IPointerClickHandler
{
void Start()
{
Camera.main.gameObject.AddComponent<PhysicsRaycaster>();
}
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("Clicked!");
}
}
For your Button, you can just subscribe to to Buttons using the Button.onClick.AddListener(() => functionName());. Below is a full code for detecting clicks on 3 buttons. The good thing about this is that only one click will be detected. Clicks will not go through other GameObjects and you are NOT allocating memory each frame just to detect a button click.
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
public Button button1;
public Button button2;
public Button button3;
void OnEnable()
{
//Register Button Events
button1.onClick.AddListener(() => buttonCallBack(button1));
button2.onClick.AddListener(() => buttonCallBack(button2));
button3.onClick.AddListener(() => buttonCallBack(button3));
}
private void buttonCallBack(Button buttonPressed)
{
if (buttonPressed == button1)
{
//Your code for button 1
//Call your SetBuilding(GameObject building) function for any button
SetBuilding(someGameOBject);
}
if (buttonPressed == button2)
{
//Your code for button 2
}
if (buttonPressed == button3)
{
//Your code for button 3
}
}
void OnDisable()
{
//Un-Register Button Events
button1.onClick.RemoveAllListeners();
button2.onClick.RemoveAllListeners();
button3.onClick.RemoveAllListeners();
}
}
I don't know if i clearly understand but you are Instantiating on the button and at the click:
ghostBuildingObject = Instantiate(building);
and
Instantiate(prefab, /* At mouse position on ground */);
so it's normal for it to be created 2 times
Have you tried with:
if(Input.GetMouseButtonUp(0) && prefab != null){
Instantiate(prefab, /* At mouse position on ground */);
prefab = null;
}
Using Pointer Events seems to fix the issue:
void Update(){
// Get pointer events
var pointer = new PointerEventData(EventSystem.current);
pointer.position = Input.mousePosition;
// Test the raycast
List<RaycastResult> raycastResults = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointer, raycastResults);
// Check if anything was cast
if(Input.GetMouseButtonUp(0) && raycastResults.Count == 0 && prefab){
Instantiate(prefab, /* At mouse position on ground */);
prefab = null;
}
}

Unity3d progress bar

I am developing a game using unity3D and I need help making a progress time bar such that on collecting particular items time is added and thus the game continues.
Create a UI Image that is of type Filled. Use horizontal or vertical fill depending on your progress bar. Then from inside a script you can manipulate the value of the image. I will give you a very simple c# example. For the rest you can just use google and read the unity scripting API.
public class Example: MonoBehaviour {
public Image progress;
// Update is called once per frame
void Update ()
{
progress.fillAmount -= Time.deltaTime;
}
}
U could use a slider en slider.setvalue.
Example:
//to use this add first a slider to your canvas in the editor.
public GameObject sliderObject; //attachs this to the slider gameobject in the editor or use Gameobject.Find
Slider slider = sliderObject.GetComponent<Slider>();
float time;
float maxtime; //insert your maxium time
void start(){
slider.maxValue = maxtime;
}
void update()
{
time += Time.deltaTime;
if (time < maxtime)
{
slider.value = time;
}
else
{
Destroy(sliderObject);
//time is over, add here what you want to happen next
}
}

unity particle doen't play second time

I have a particle system defined in my game objects. When I call Play it plays (it plays for 5 seconds by design). when I call Play again nothing happens. I tried to call Stop and Clear before recalling Play but that didn't help.
Can particle systems play more than once?
My code is in this method, which is called when a button is clicked.
public void PlayEffect()
{
for (int i=0;i<3;i++)
{
NextItemEffectsP[i].Stop();
NextItemEffectsP[i].Clear();
NextItemEffectsP[i].Play();
}
}
NextItemEffectsP is an array that contains particles that I populate in the editor
You should rework how your bullet works. Have some code on the bullet Prefab to control when it gets destroyed.
private float fuse = 1.0;
private float selfDestructTimer;
void Awake() {
// Time.time will give you the current time.
selfDestructTimer = Time.time + fuse;
}
void Update() {
if (selfDestructTimer > 0.0 && selfDestructTimer < Time.time) {
// gameObject refers to the current object
Destroy(gameObject);
}
}
Then with that control set up, you'll always just create new bullets whenever the fire button is pressed.

Categories