I am trying to make a chat dialogue in unity which should show up when colliding with an object and press a key. The chat dialogue should remain until collision exit. The issue is that the chat dialogue shows up on key press when in collision but turns false in the same second so it flickers. the bool is being reset instead of remaining true while in collision.
hitColliders = Physics.OverlapSphere(transform.position, 5f);
int i = 0;
while (i < hitColliders.Length) {
if (hitColliders [i].gameObject.tag == "gameobjectCollision") {
if (Input.GetKey (KeyCode.F)) {
Debug.Log ("pressed F");
DialogueController.showConversation = true;
}
break;
}
else {
Debug.Log ("Conversation Off");
DialogueController.showConversation = false;
}
i++;
}
Also, script is being attached properly and mesh collider is set with colliding game object. Thanks.
You could do the following
Generate an event from OnTriggerEnter.
Create an ChatDialogueHandler Script and an add listener to that event.
Enable the chat dialogue box when event is raised and disable the chat dialogue box after some specific time.
You should really think about doing this off of triggers and not collision. So making a separate trigger box for each NPC that you can talk to in your game. And then make use of OnTriggerEnter and OnTriggerExit in your player script. OnTriggerEnter you can allow the conversation to start by a button click, and then OnTriggerExit you can turn off the coversation.
public void Update()
{
if (inInteractRange && Input.GetKeyDown(KeyCode.E))
{
DialogueSystemManager.Instance.StartDialogueForNpc(interactableNPCName);
}
}
private void OnTriggerEnter(Collider col)
{
inInteractRange = true;
}
private void OnTriggerExit(Collider col)
{
inInteractRange = false;
DialogueSystemManager.Instance.CloseDialogueWindow();
}
Related
I am creating a game in unity where the player can drag one object (a card) over another (an enemy). If they drag the card over the enemy I want to run some code, and if not I want to return the card to its initial position. I placed a collider on both objects but it isnt working the way it should. I am assuming this is because the object is getting moved back to its initial location before the physics engine sees the collision, but I don't know how to fix this. I am deactivating the collider on the card while moving it to avoid having it trigger collisions until the player has placed it using the onmousedown and onmouseup events. Any tips on how to fix this behavior? can I force the physics engine to check collisions with the onmouseup event?
I know the collisions are working because when I turn off the return to initial position behavior the game functions as expected.
How about useing the collider as trigger and do not use rigidbodys or anything.
Then if there is a trigger enter event set bool as true. If there trigger exit reset the bool to false.
Now if you "Release" the card check if bool is true or false.
true: Set the cards position to the player or what you want
false: Reset the cards position to the start
Now beeing a little mroe fancy you can set a lighted border around the card when bool is active (just check in update)
Example:
public class Card : MonoBehaviour {
private bool isHolding;
private bool isHovering;
public Vector3 startPos;
public void Start() {
startPos = transform.position;
}
public void Update() {
// Code where you check if the card is Clicked and Moved by the player
// If so set isHolding = true
// dont enter the check if holding blablabla when animation stuff is happening
if (doAnimationStuff) {
// do animation
// Destroy Object
return;
}
// Code to check if isHolding == false
if (!isHolding) {
if (!isHovering) {
transform.position = startPos;
} else {
doAnimationStuff = true;
}
}
}
private void OnTriggerEnter(Collider other) {
// Check if other is a player
// if so set isHovering = true
}
private void OnTriggerExit(Collider other) {
// Check if other is a player
// if so set isHovering = false
}
}
Some part of the code works (hp1 -= damage1;), but the second part doesn't work.
Where did I make a mistake?
Here are parts of two scripts:
Player1.cs
private Bullet1 b1;
void Start()
{
b1 = FindObjectOfType<Bullet1>();
}
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "Bullet1")
{
hp1 -= damage1; // it works, my player loses hp
Destroy1(); // doesn't work
}
}
void Destroy1()
{
b1.hit1 = true; // hit for bullet1.cs
}
Bullet1.cs
public bool hit1;
void Update()
{
if (hit1)
{
hit1 = false;
Destroy(gameObject);
}
}
If I switch bool hit = true in real time in Unity, destroying works. It means that Bullet1.cs can't recieve hit = true;
If I swap lines hp1 -= damage1; and Destroy1();, my player can't get damage. So, Destroy1(); stops my code and then can't activate other lines. Also if I change Destroy1(); to b1.hit1 = true; nothing new happens.
Just destroy the bullet through the collision instead of using the boolean. It's creating unnecessary resource usage. Of the given code, this is all you need to do to destroy the bullet using the player script. The parts of the bullet script shown are unnecessary. If you want additional logic handled inside the bullet when destroyed then use a OnDestroy function to handle it.
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.tag == "Bullet1")
{
hp1 -= damage1;
Destroy(col.gameobject);
}
}
Anyone can help me how to fix this problem i'm having?
*1st script:
public static bool attacking;
public Collider2D attackTrigger;
private void Awake()
{
attackTrigger.enabled = false;
}
private void Update()
{
if (attacking == true)
{
Debug.Log("Box Collider Enabled");
attackTrigger.enabled = true;
StartCoroutine(DisableCollider());
}
}
IEnumerator DisableCollider()
{
yield return new WaitForSeconds(1);
attacking = false;
attackTrigger.enabled = false;
Debug.Log("Box Collider Disabled");
}
*2nd script:
public float damage = .10f;
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.isTrigger!=true && collision.CompareTag("Enemy"))
{
Debug.Log("Enemy is Damaged");
EHealthBar.TakeDamage(damage);
}
}
i'm trying to get my player character to attack an enemy using collision, well it does work and the player does damage the enemy but it will only work if the enemy's box collider enters my attack again.
if the enemy is already in my area of attack which has a box collision 2d attached, the enemy doesn't get damaged and that's not what i was going for.
I can change it to OnTriggerStay2D but the enemy will keep on getting damaged till the collider is disabled again. care to help?
I think the problem is
IEnumerator DisableCollider()
{
yield return new WaitForSeconds(1);
attacking = false;
...
which causes that your IF statement in your update is still occuring for 1 second and starting a lot of coroutines. The easiest solution would be moving attacking = false; before yield, but i guess you want to use that variable to be aware if user is in attack state. So i suggest to use another bool variable.
if (invokeAttack)
{
attacking = true;
invokeAttack = false
Debug.Log("Box Collider Enabled");
attackTrigger.enabled = true;
StartCoroutine(DisableCollider());
}
Anyway, you didn't show us how you invoke attack, but maybe instead of changing variable (attacking/invokeAttack in your case) to true and checking it in Update you just invoke a method which enables collider and starts coroutine?
I have animation Clip for swinging sword. At a specific frame, I added Event. I want when player swing sword, in that case only the enemy could die.
So I added the following OnTriggerEnter Code
void OnTriggerEnter(Collider col)
{
hit = true;
if (hit)
{
if (col.GetComponent<Collider>().tag == "enemy")
{
Destroy(col.gameObject);
}
}
}
When I try to add function OnTriggerEnter (in animation Clip) as animation Event, it is asking me to pass Collider parameter, Which i am not able to add.
Here is the screen shot of Add Event
Please help me , how can I add event with collider ( as parameter ) at a specific frame.. Thanks
Collision and Trigger events are called on their own on every frame.
Call another public method from animation event for your task and put necessary Boolean or Enum there to control collision, trigger after swinging the sword.
public void SwingingSword()
{
isSwingingSword = true; // make it false when not swinging the sword.
}
void OnTriggerEnter(Collider col)
{
hit = true; // not sure what it's job here
if (isSwingingSword && hit)
{
if (col.GetComponent<Collider>().tag == "enemy")
{
Destroy(col.gameObject);
}
}
}
I writing runner game on Unity (C#) for mobile phones.
I made Pause button on screen, using Canvas - Button.
Also I made code for Pause in Platformer2DUserControl script.
Here it is code of this script:
using UnityEngine;
using UnitySampleAssets.CrossPlatformInput;
namespace UnitySampleAssets._2D
{
[RequireComponent(typeof(PlatformerCharacter2D))]
public class Platformer2DUserControl : MonoBehaviour
{
private PlatformerCharacter2D character;
private bool jump;
public bool paused;
private void Awake()
{
character = GetComponent<PlatformerCharacter2D>();
paused = false;
}
private void Update()
{
/*if (Input.GetButton("Fire1"))
{
}*/
if (!jump)
// Read the jump input in Update so button presses aren't missed.
jump = Input.GetButton("Fire1"); //&& CrossPlatformInputManager.GetButtonDown("Jump");
}
private void FixedUpdate()
{
// Read the inputs.
bool crouch = Input.GetKey(KeyCode.LeftControl);
// float h = CrossPlatformInputManager.GetAxis("Horizontal");
// Pass all parameters to the character control script.
character.Move(1, false, jump);
jump = false;
}
public void Pause()
{
if (!jump)
// Read the jump input in Update so button presses aren't missed.
jump = Input.GetButton("Fire1"); //&& CrossPlatformInputManager.GetButtonDown("Jump");
paused = !paused;
if (paused)
{
jump = !jump;
Time.timeScale = 0;
}
else if (!paused)
{
// jump = Input.GetButton("Fire1");
Time.timeScale = 1;
}
}
}
}
My Pause Button is WORKS well. But when I tap it , my character is jumping and game is pausing.
I want to make that , when I tapping the button game just pausing and character don't jump.
How I can make it. Thank's for help.
I would advise you not to use the same input for jumping and pausing. Also, separate your jump and pause functionalities into separate functions. For pausing, create a UI button on the screen and make it call a public function on a Pause script, that will toggle pause. Then, in the same function, check if you are paused or not and adjust Time.timescale accordingly
You will have to attach the script with pause functionality on to an object that will always be in a screen (Say, a panel in your canvas or your MainCamera). Under the button, add a new onClick() function after dragging the GO with the apt script to the box. Then, select the public function aforementioned.
private bool paused = false;
//The function called by the button OnClick()
public void TogglePause()
{
paused = !paused;
if(paused)
Time.timescale = 0f;
else
Time.timescale = 1f;
}
Hope this helped!
Well, your code is messed up, but just remove the jump script from the pause method. So it will just pause...
public void Pause()
{
paused = !paused;
if (paused)
{
Time.timeScale = 0;
}
else
{
Time.timeScale = 1;
}
}
Note that Input.GetButton should only be called in Update
EDIT
The problem that you have to tap your screen to press the button. And the code jump = Input.GetButton("Fire1"); basically means "Am I tapping the screen?" So both JUMP and PAUSE are triggered.
One solution would be to put a canvas filling the whole screen under your buttons. You will trigger a JUMP action only when this canvas is clicked. So when you click your pause button, it will stop the propagation and won't click the full screen canvas, which won't trigger the jump action.
EDIT2
Try changing the lines (in the Update function) :
if (!jump)
// Read the jump input in Update so button presses aren't missed.
jump = Input.GetButton("Fire1");
for :
if (!jump && !paused)
// Read the jump input in Update so button presses aren't missed.
jump = Input.GetButton("Fire1");
I think the button event is called before the Update, see reference
One solution would be possible make sure the raycast on of pause button.
I have always done it like this, essentially surround the entire fixed update (or wherever you have your game motion) with the paused-bool
private void FixedUpdate()
{
if (paused != true){
// Read the inputs.
bool crouch = Input.GetKey(KeyCode.LeftControl);
// float h = CrossPlatformInputManager.GetAxis("Horizontal");
// Pass all parameters to the character control script.
character.Move(1, false, jump);
jump = false;
}
}