I am returning to unity after 6 months. I started my fps game yesterday. Today I was trying to make C4 bomb, which worked as follows: the c4 will already be placed, you just have to activate using a remote. In the start the remote will not be in your hand, you have to press F1 to set it active. To put the remote away again, we have to press F2. But the problem is that it won't detect my F1 key press. Here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class C4Script : MonoBehaviour
{
public GameObject remote;
private bool remoteHand;
// Start is called before the first frame update
void Start()
{
remote.SetActive(false);
remoteHand = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.F1) && !remoteHand)
{
remote.SetActive(true);
remoteHand = true;
}
if (Input.GetKeyUp(KeyCode.F2) && remoteHand)
{
remote.SetActive(false);
remoteHand = false;
}
}
}
The code may be wrongly formatted, I am sorry for that.
Also sorry if I didn't explain it properly.
Thanks!
The code works on my machine, do you maybe have the C4Script or the Gameobject on which it is attached disabled?
Looks like the script is never called rather then that it's not detecting the input. You could add an Debug log or debug breakpoint to the start method to check if it's ever called.
Soo, the problem was that i am dumb. i Put this script on the remote, and at the start it disables the remote thats why it wasn't detecting my key press. I put the script on my player object and now it works fine.
Related
I am trying to create an infinite runner.
My scene have a "road creator" object that is just a trigger and a script attached to my road prefab.
Every time a piece of road leaves the road creator trigger, a new piece of road is created.
Here's the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class roadGenerator : MonoBehaviour
{
public GameObject road;
private void OnTriggerExit(Collider other) {
if(other.gameObject.tag == "roadGenerator"){
Instantiate(road, new Vector3(200, 0, 0), Quaternion.identity);
}
}
}
My issue is that once the player loses and the level reloads the script stops working.
Everything gets loaded properly (the trigger object and the first piece of road with the script attached) but for some reason the script doesn't get triggered...
Hey I think I'll need some more context to understand your problem:
You have a "roadGenerator" with a trigger and the Script attached + a "Road" Prefab with the Tag "roadGenerator" right?
I suppose by "realoading the level" you mean reloading the Scene with something like SceneManager.LoadScene(...)
It would also be good to know what you already tried out to fix it. :)
I want my Player to interact with object, so I use Fungus and a script that when the Player is close enough to the object and I press E, it sends a message to Flowchart to activate a block. But it doesn't work.
The script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EventTrigger : MonoBehaviour
{
public bool enter;
int count = 1;
// Use this for initialization
void Start()
{
enter = false;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player" || other.gameObject.tag == "NPC")
{
enter = true;
if (enter && Input.GetKeyDown(KeyCode.E))
{
Fungus.Flowchart.BroadcastFungusMessage("StartConversation");
}
}
Debug.Log("Entered");
}
void OnTriggerExit(Collider other)
{
if (other.gameObject.tag == "Player" || other.gameObject.tag == "NPC")
{
enter = false;
count = 1;
}
Debug.Log("Exited");
}
}
OnTriggerEnter is called once, and you are listening to input only during one frame.
Consider moving this part to Update:
if (enter && Input.GetKeyDown(KeyCode.E))
{
Fungus.Flowchart.BroadcastFungusMessage("StartConversation");
}
or changing OnTriggerEnter to OnTriggerStay
I'm unfamiliar with Fungus, however, as mentioned in the comments, you're having trouble getting the event to be called upon Collision.
Please take the following into account:
Colliders must be marked IsTrigger for OnTriggerXXX to be called, however, trigger colliders are non-physical, this means if you only have 1 trigger collider in your gameobject, other physical objects can pass through them. To fix this, you can either add a second collider with IsTrigger unchecked, OR, you can uncheck IsTrigger and use OnCollisionXXX instead. I'd suggest the latter solution.
Make sure your colliders can actually collide.
Go to "Edit > Project Settings > Physics", scroll down until you see "Layer Collision Matrix" and make sure the checkbox in the intersection of your objects' layers is checked.
Make sure the two colliders can actually collide during play. This is common with character collisions. You might have a simple box or cylider physical collider around your characters, but have an inner mesh collider be the trigger on your NPC. This way your player character can never collide with the trigger inside the physical collider.
This may sound stupid, but make sure you added your script to correct object. I've lost the count of how many times I went through an unecessary frustration after writting a script and forgetting to add it to the test object.
This should be enough to ensure your events are actually called.
Now, please note that, as pointed out by Hermesis, you're trying to read input in a 1-frame event. You're also using Input.GetKeyDown() which is also a 1-frame check, that is, it will only return true on the frame when the key state has changed.
In your code, the condition (enter && Input.GetKeyDown(KeyCode.E)) will only ever be true, if the user happens to press the key in the exact frame the collision begins.
Again, as noted by Hermesis, consider using "OnXXXStay" instead of "OnXXXEnter".
Here are some tips:
Use OnXXXEnter to display a message to the player so he knows he is in contact with an interactable, and also knows which key(s) can do what.
Use OnXXXStay to respond to keypresses only while the collision is happening.
Use OnXXXExit to clear the message that was set upon collision.
I hope this helps.
I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.
I'm making a multiplayer bomberman game using Unet. I'm trying to create a ready check to start the game when everyone else is ready.
I tried using a sync var,Command and Rpc calls, but nothing seems to work properly.
When using a Cmd call this way (called when a player pushes the ready button)
[Command]
private void CmdIncreaseReady()
{
IncreaseReady();
RpcIncreaseReady();
}
[ClientRpc]
private void RpcIncreaseReady()
{
IncreaseReady();
}
private void IncreaseReady() {
playersReady++;
//ChechAllReady();
}
When pressed on the client, everyone's counter is 0 (it should be one), and when pressed on the server, the server's counter is 2 and the client 1.
I've tried to call Cmd when !isServer and Rpc when it is, and the result is that stills doesn't update when pressed on the client, but it is updated correctly (the counter is 1 on both), when pressed on the server.
if (!isServer)
{
CmdIncreaseReady();
}
else
{
RpcIncreaseReady();
}
If I delete the IncreaseReady() call on the Cmd, the result is the same than above.
I've tried too to use a [SyncVar] to the counter, with and without a hook, passing 1 on the hook (to increment the counter that amount) and passing the already counter incremented and set variable to that number, nothing seems to work.
I really don't know how to make it work anymore. Could someone help me? I'm really desperate with this. I've searched everywhere.
The script is the game manager, when every client has his version, it has a Netework Identity and has Local player Authority.
I've tried another approach, passing the increased number on the Cmd and Rpc, and inside the functions, just set the playersReady = i. Even that doesn't work.
[UPDATE]:
So, I've found the specific problem that I want to solve, and it's to Sync non-player objects properties.
I've tried to spawn the Game Manager with Client Authority, and now it seems to sync correctly only on the server, the client stills doesn't call the Cmd propety.
Looking at the Debug mode in the inspector, I've been able to see that on the server, hasAutority is true, but is false on the client.
This is a fragment of the code on the player script where I spawn the game manager:
void Update()
{
if (!sceneLoaded)
{
if(isServer & SceneManager.GetActiveScene().name == "Main Scene")
//if (SceneManager.GetActiveScene().name == "Main Scene")
{
if (connectionToClient.isReady)
{
var go = (GameObject)Instantiate(gameManager);
NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
go.transform.SetParent(null);
//go.GetComponent<NetworkIdentity>().AssignClientAuthority(connectionToClient);
globalManager = go.GetComponent<FSM>();
//SetFSM();
sceneLoaded = true;
}
}
}
UNET has a Lobby system which does exactly what I think you want. It has a per-player ready state, so that the game starts when all players are ready.
I would recommend using that, as it saves you having to reimplement things like dropping out, rejoining etc...
I have a code like the following:
void Update()
{
if(Input.GetMouseButtonDown(1))
{
Debug.Log("foo");
}
}
The problem is that if I click the right mouse button once the "foo" is written twice. How is it possible?
As Frohlich stated in comment, If you attach a script on more than one GameObject you will be getting Update method call per frame for each script in scene. So to check that you should use Debug.Log() method as follow:
Debug.Log("foo",gameObject);
and when you will click on log in console window, it will take you to the gameObject which is generating that log.