using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DroidMove : MonoBehaviour
{
public GameObject droid;
private void Start()
{
droid.SetActive(false);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
droid.transform.position = droid.transform.position - transform.forward;
droid.SetActive(true);
}
}
}
I want that once I click on D it will show the Droid and also when I move the camera(transform) the droid will follow the camera.
And when I click once again on D set the droid active to false so each time I click on D it will toggle between SetActive false and true.
For toggling an object you should use something like this. PSEUDO
if (Input.GetKeyDown(KeyCode.D))
{
droid.enabled = !droid.enabled;
}
This will allow you to toggle your gameObject each time you press the button D.
In KeyDown
droid.transform.position = droid.transform.position - transform.forward;
This will work only once (One Frame). So you can use a bool or check if your gameObject is active to follow your camera. In Update you can use the following
if (droid.activeInHierarchy == true) // or you can use a bool here
{
droid.transform.position = droid.transform.position - transform.forward;
}
Hope this helps. Cheers!
Related
I was creating a flappy bird game in Unity and while I was trying to add touch inputs it gave me this error
InvalidOperationException: You are trying to read Input using the
UnityEngine.Input class, but you have switched active Input handling
to Input System package in Player Settings.
I think it's because I downloaded the new Input system from the package manager, but i removed it
playerScript Code:
using UnityEngine;
public class playerScript : MonoBehaviour
{
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0) || Input.touchCount > 0)
{
rb.velocity = new Vector2(0f, 7f);
}
}
}
Solved it!
You need to go to the Player settings Build settings/Player settings/Other settings/Configuration and search for:
and set Input manager old
Try change code to this
using UnityEngine;
public class playerScript : MonoBehaviour
{
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Jump();
}
}
public void Jump()
{
rb.velocity = new Vector2(0f , 7f);
}
}
Then add UI button and on the on click drag the gameobject this script is attacked to into it, click the script and then click 'Jump()'
You could add Giant UI button and add function jump and make it work when button is pressed. I had similar problem for visual novel game. And I added screen sized button :)
I'm developing a 2D mobile game where the player should tap on the screen to go up. I just added a pause button recently and I've noticed that when I click the button it counts as a tap on the screen, so the player goes up. Basically, in the same exact moment that I press the pause button, the player jumps and then the game freezes while he is in mid-air. Is there a way I could make so the button wouldn't count as a tap?
Here's the part of the player script that makes him move:
if (Input.GetMouseButtonDown (0) && isDead == false && isKnifeDead == false && UiStartScript.uiInstance.firstClickUi == true) {
rb.velocity = Vector2.up * velocity;
}
Heres's the part of the UI script for the pause button:
public void PauseGame()
{
Time.timeScale = 0;
}
My EventSystem:
EventSystem
My Button:
Button
An easy with no code required is to remove the code about detecting tap on screen and instead place a button that covers the whole screen (invisible button).
That button event would trigger the screen movement.
You can add extra buttons on top and Unity will automatically discard the tap from any other button below.
This way you can start adding UI all over without checking in code which should be considered.
In U. I script add
public GameObject PlayerConrtollerScript;
In your U.I Script, under the class Pausgame()
Add this code.
GameObject.PlayerControllerScript.SetActive = false;
When unpaused you need to add to your script that has the
Time. timeScale =1;
Add this code.
GameObject.PlayerControllerScript.SetActive = true;
After you have added the code mentioned above. Don't forget to add the player game object from your hierarchy into the Inspector with the U. I script, the space will be available to add a game object when you scroll down to your U. I script.
That will stop your player from moving around during pause.
This is the approach that I been done. I create a cople of tricks using Event System and Canvas for take advantage of the Mouse Input, you don't need the use of Updates functions for do the basic gameplay.
Here's my example project: TapAndJump on Github
Check the GameObjects called "Click Panel" and "Pause Button" and
respective linked methods.
JumpWithTap.cs
using UnityEngine;
public class JumpWithTap : MonoBehaviour
{
[SerializeField] private UIHandler uiHandler;
[SerializeField] private float jumpPower = 5f;
private Rigidbody2D rb2D;
private int counter;
#region Class Logic
public void Jump()
{
rb2D.velocity = Vector2.up * jumpPower;
uiHandler.SetNumberToCounter(++counter);
}
#endregion
#region MonoBehaviour API
private void Awake()
{
rb2D = GetComponent<Rigidbody2D>();
}
#endregion
}
UIHandler.cs
using UnityEngine;
using UnityEngine.UI;
public class UIHandler : MonoBehaviour
{
[SerializeField] private Text counterText;
[SerializeField] private Text pauseText;
[SerializeField] private Image clickPanel;
private bool isPaused = false;
public bool IsPaused
{
get { return isPaused; }
set
{
pauseText.gameObject.SetActive(value);
isPaused = value;
}
}
#region Class Logic
public void SetNumberToCounter(int number) => counterText.text = number.ToString();
public void DisableClickPanel() => clickPanel.raycastTarget = !clickPanel.raycastTarget;
public void PauseGame()
{
IsPaused = !IsPaused;
DisableClickPanel();
// Time.timeScale = IsPaused == true ? 0 : 1; // If you want keep the Physics (ball fall) don't stop the time.
}
#endregion
}
I guided by your code example and so on; be free that modify and request any issue.
I am trying to change the image of a sprite that's had a long click on it.
My below code works except in the LongPress method it changes the image of all sprites that have this script assigned as an inspector component. Additionally, the code triggers after long clicking anywhere onscreen, not isolating itself to just the sprites with the script assinged
OnMouseDownAsButton would solve a lot of the issues, however wrapping bits of my code in an OnMouseDownAsButton function to isolate the colliders seems to cancel out the update() method.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class LongClickButton : MonoBehaviour
{
public Sprite flagTexture;
public Sprite defaulttexture;
public float ClickDuration = 2;
public UnityEvent OnLongClick;
bool clicking = false;
float totalDownTime = 0;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
totalDownTime = 0;
clicking = true;
}
if (clicking && Input.GetMouseButton(0))
{
totalDownTime += Time.deltaTime;
if (totalDownTime >= ClickDuration)
{
clicking = false;
OnLongClick.Invoke();
}
}
if (clicking && Input.GetMouseButtonUp(0))
{
clicking = false;
}
}
public void LongPress()
{
if (GetComponent<SpriteRenderer>().sprite == flagTexture)
{
GetComponent<SpriteRenderer>().sprite = defaulttexture;
}
else if(GetComponent<SpriteRenderer>().sprite == defaulttexture)
GetComponent<SpriteRenderer>().sprite = flagTexture;
}
}
Try using OnMouseDown functions and OnMouseUpAsButton. Your current issue seems that the Input detects of a mouse down anywhere on screen, which causes all scripts to activate, which causes the changes.
void OnMouseDown() {
clicking = true
}
void OnMouseUpAsButton(){
clicking = false
}
void Update() {
if(clicking){
//your time stuff
}
}
You could add a EventTrigger component to the gameobject with the "OnPointerEnter" and "OnPointerExit" events to check if the mouse is on that object (Make OnPointerEnter call a function that sets a boolean to true and OnPointerExit to set that boolean to false).
What you could do is make your script implement interafaces IPointerEnterHandler, IPointerExitHandler found in namespace UnityEngine.EventSystems. Inside onPointerEnter and onPointerExit you could set a value of boolean variable.
I want to move my player around in my level without a NavMesh Agent.
I was thinking something about raycasting, but i have tried everything and even looked up videos and searched on google about it, can't seem to find anything that works
Plz help!
you can use this for moving to mouseclick position.
This method will move object or player to the position where mouse is clicked on screen.
sorry for syntax error i have typed directly here
using UnityEngine;
using System.Collections;
public class MouseMovement : MonoBehaviour
{
public float speed = 10f;
bool isplayermove = false;
// Use this for initialization
private void Start ()
{
Vector3 playerpos = transform.position;
}
// Update is called once per frame
private void Update ()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
is moveplayer = true;
}
if(ismoveplayer)
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(input.mousepos.x,input.mousepos.y,input.mousepos.z);
transform.position = Vector3.MoveTowards(transform.position,new Vector3(mousepos.x,transform.position.y,mousepos.z),speed * time.deltatime);
if(transform.position == mousepos)
{
ismoveplayer = false;
}
}
}
}
First a screenshot of my Hierarchy :
Everything is inside a one scene name The :
The game start when Main Game is disabled. Inside Main Game sit all the game objects. The Main Menu and Game Manager are enabled.
When running the game first time, When the game start there is short animation of the player for 5 seconds. The player start from some rotating degrees on Z. Z = 50 when x and y both are 0. Then the player is rotating slowly over the Z to 0.
It's like the player is sleeping and awake up.
I'm using post processing stack by unity.
And here is the first problem. While the player is rotating on the Z and post processing effect is working if I press the Escape key it will bring me back to the Main Menu but then if I press the Escape key again it will start the game over again from the begin.
But if I'm waiting in my game for the player to finish rotating on the Z and the post processing effect is finished and then pressing on Escape it will bring the main menu and second time will resume the game from the same point.
I can't figure out why when the player is rotating and the post process is working the escape key make it start the game over again from the being ?
This is a screenshot of the game when start and after finish the rotating and the process stack :
Another problem I noticed now. After the game start using the post process and the player rotating finished if I press Escape it will go to main menu and escape again will be back to the game but for example in the second screenshot the conversation is not continue. It will return to the same point in the game but things not seems to continue like the conversation.
On the Back to main menu object I have a script attached to it :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class BackToMainMenu : MonoBehaviour
{
private bool _isInMainMenu = false;
public GameObject mainGame;
public GameObject mainMenu;
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (!_isInMainMenu)
{
// -- Code to freeze the game
mainGame.SetActive(false);
mainMenu.SetActive(true);
}
else
{
// -- Code to unfreeze the game
mainGame.SetActive(true);
mainMenu.SetActive(false);
}
_isInMainMenu = !_isInMainMenu;
}
}
}
On the Main Menu object under Main Menu I have attached this script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MainMenu : MonoBehaviour
{
public GameObject mainGame;
public GameObject mainMenu;
public void PlayGame()
{
mainGame.SetActive(true);
mainMenu.SetActive(false);
}
public void QuitGame()
{
Application.Quit();
}
}
On the PLAY button I'm using this script method PlayGame from the MainMenu script.
In the Main Game object on the Player object attached to thew Player I have some scripts the controller :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed = 10.0f;
// Update is called once per frame
void Update()
{
float translatioin = Input.GetAxis("Vertical") * speed;
float straffe = Input.GetAxis("Horizontal") * speed;
translatioin *= Time.deltaTime;
straffe *= Time.deltaTime;
transform.Translate(straffe, 0, translatioin);
}
}
Player Lock Manager :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerLockManager : MonoBehaviour
{
public PlayerCameraMouseLook playerCameraMouseLook;
public PlayerController playerController;
// Start is called before the first frame update
public void PlayerLockState(bool LockPlayer, bool LockPlayerCamera)
{
if (LockPlayer == true)
{
playerController.enabled = false;
}
else
{
playerController.enabled = true;
}
if (LockPlayerCamera == true)
{
playerCameraMouseLook.enabled = false;
}
else
{
playerCameraMouseLook.enabled = true;
}
}
}
And Mouse Lock State :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MouseLockState : MonoBehaviour
{
public bool lockState = true;
private void Start()
{
LockState(lockState);
}
private void Update()
{
}
public void LockState(bool lockState)
{
if (lockState == false)
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
else
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
}
}
Under the Player as child I have the Player Camera object and attached to the Player Camera also some scripts :
Player Camera Mouse Look :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCameraMouseLook : MonoBehaviour
{
public float sensitivity = 5.0f;
public float smoothing = 2.0f;
private GameObject player;
private Vector2 mouseLook;
private Vector2 smoothV;
// Use this for initialization
void Start()
{
player = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update()
{
var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
mouseLook += smoothV;
mouseLook.y = Mathf.Clamp(mouseLook.y, -90f, 90f);
transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
player.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, Vector3.up);
}
}
And Depth Of Field script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfField : MonoBehaviour
{
public GameObject player;
public PostProcessingProfile postProcessingProfile;
public bool dephOfFieldFinished = false;
public PlayerLockManager playerLockManager;
private Animator playerAnimator;
private float clipLength;
// Start is called before the first frame update
void Start()
{
playerAnimator = player.GetComponent<Animator>();
AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
foreach (AnimationClip clip in clips)
{
clipLength = clip.length;
}
var depthOfField = postProcessingProfile.depthOfField.settings;
depthOfField.focalLength = 300;
StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, clipLength));
postProcessingProfile.depthOfField.settings = depthOfField;
}
IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
{
playerLockManager.PlayerLockState(true, true);
float counter = 0f;
while (counter < duration)
{
var dof = postProcessingProfile.depthOfField.settings;
if (Time.timeScale == 0)
counter += Time.unscaledDeltaTime;
else
counter += Time.deltaTime;
float val = Mathf.Lerp(fromVal, toVal, counter / duration);
dof.focalLength = val;
postProcessingProfile.depthOfField.settings = dof;
yield return null;
}
playerAnimator.enabled = false;
dephOfFieldFinished = true;
}
}
I have under Main Game also a object name Openning Scene and attached to it :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OpeningCutscene : MonoBehaviour
{
public NaviConversations naviConversation;
public DepthOfField dephOfField;
// Update is called once per frame
void Update()
{
if (dephOfField.dephOfFieldFinished == true)
{
naviConversation.PlayNaviConversation(0);
dephOfField.dephOfFieldFinished = false;
}
}
}
It's a bit long but everything is connected.
The game start with the main menu.
When clicking the PLAY button a new game start.
When a new game start the script Depth Of Field is in action using the post processing. Also I'm locking the player so the player will not be able to move either the mouse or the player it self.
When the depth of field script finished his work a conversation between Navi and the Player start. When a conversation is in action the player can move the mouse 360 degrees but cant move the player to any direction.
When the conversation ended the player can also move to any direction.
Problems :
When start a new game while the depth of field script is in work pressing escape will bring the main menu but pressing escape again will not resume the depth of field script but will start it all over again.
When waiting the conversation to end if not pressing escape until the conversation ended then when moving around and pressing escape it will bring the main menu and again will resume the game from the same point.
The problems is when the game is doing something like the depth of field it will start the game over again instead resuming or when in conversation in the middle the conversation will never continue.
The ides with the escape key is once to get to main menu and second to resume the game.
The PLAY button is what should only start a new game and not the escape key.
It's a bit long but everything is connected.
I can't see which objects you hooked up to mainGame and mainMenu in BackToMainMenu from your hierarchy, so I have some conjecture in here.
Sounds like you want Escape key to pause, and unpause, as well as bring up a menu, you want Play button in the menu to restart your game.
However, in both MainMenu and BackToMainMenu you use the same code:
mainGame.SetActive(true);
mainMenu.SetActive(false);
This just turns the objects on and off in the hierarchy. This means the first time you do one of these things, all objects turned on under the gameobject referenced by mainGame will run their Awake and Start methods, but not the second time. Also depending which objects are active (like I said I can't fully see what component is on what object and which objects are referenced by which serialized field) you might be able to introduce a state error on BackToMainMenu._isInMainMenu because that field isn't changed when you hit play. Here is a fantastic image showing execution timeline in Unity:
Monobehavior Timeline
In summary:
The second time you run the game DepthOfField won't call Start a second time. Instead try OnEnable.
The conversation and game logic is not shown in your post, but likely it also is initializing in Start and won't run a second time.
A bit of trickiness around Coroutines is likely to blame here. When DepthOfField starts it also starts a coroutine. That coroutine keeps going even if you set the gameobject inactive. So you run the game once, that coroutine starts, you turn the object off when you hit escape, the coroutine finishes, you hit play again, but DepthOfField.dephOfFieldFinished == true and your playerAnimator is disabled and won't enable again.
Also 5. This kind of behavior can be tricky and is usually dependent on what else you have going on in your scene. Since you have one scene with everything at once, you need to watch out for putting stuff in Awake and Start since this will only run once. Instead you can try a number of things, my favorite is usually to set up a singleton or static class that works as a state machine for the whole scene. It will call custom Initialize functions in your behaviors instead of using Awake and Start.
Keep references to your coroutines by doing things like:
private Coroutine depthOfFieldRoutineRef;
private OnEnable()
{
if (depthOfFieldRoutineRef != null)
{
StopCoroutine(depthOfFieldRoutineRef);
}
depthOfFieldRoutineRef =
StartCoroutine(changeValueOverTime
(depthOfField.focalLength, 1, clipLength));
// Don't forget to set depthOfFieldRoutineRef to null again at the end of routine!
}
For simple pausing behavior you can also try setting Time.timescale = 0; and back to 1 when you want play to resume.
Less a question than a set of problems, hopefully this set of solutions helps!
Tutorial on Awake and Start
Docs on Coroutines
Docs on Time.timescale