synchronize bool in all client networking - c#

i'm trying to develop a multiplayer game .
I declared a bool variable which must be synchronized by the server.
this is my code :
public GameObject blueBar, redBar;
public GameObject barH, barV;
[SyncVar] public bool localTurn;
void Start ()
{
localTurn = true;
if (!isLocalPlayer)
{
Cmdbars();
}
}
void Update ()
{
OnClick();
}
[Command]
void Cmdbars()
{
GameObject bar1 = Instantiate(barH, GameObject.Find("pos1").GetComponent<Transform>().transform.position, Quaternion.identity) as GameObject;
NetworkServer.Spawn(bar1);
}
private void OnClick()
{
if (Input.GetMouseButtonDown(0))
{
Vector2 origin = new Vector2(
Camera.main.ScreenToWorldPoint(Input.mousePosition).x,
Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
CmdOnClick(origin.x, origin.y);
}
}
[Command(channel = 0)]
private void CmdOnClick(float x, float y)
{
RpcClick(x, y);
}
[ClientRpc(channel = 0)]
private void RpcClick(float x, float y)
{
Vector2 origin = new Vector2(x, y);
RaycastHit2D hit = Physics2D.Raycast(origin, Vector2.zero, 0f);
if (hit && hit.transform.gameObject.tag.Equals("Untagged") && localTurn)
{
hit.transform.gameObject.GetComponent<SpriteRenderer>().sprite = blueBar.GetComponent<SpriteRenderer>().sprite;
hit.transform.gameObject.tag = "ok";
CmdclientPlaying();
}
if (hit && hit.transform.gameObject.tag.Equals("Untagged") && !localTurn)
{
hit.transform.gameObject.GetComponent<SpriteRenderer>().sprite = redBar.GetComponent<SpriteRenderer>().sprite;
hit.transform.gameObject.tag = "ok";
CmdlocalPlaying();
}
}
here are the commands to change the bool
[Command]
void CmdlocalPlaying()
{
localTurn = true;
}
[Command]
void CmdclientPlaying()
{
localTurn = false;
}
everything is going well except the the bool localTurn change in local only not in all clients.
must change boll after click in object to play alternately between players.

try to change this if block to include else if
if (hit && hit.transform.gameObject.tag.Equals("Untagged") && localTurn)
{
hit.transform.gameObject.GetComponent<SpriteRenderer>().sprite = blueBar.GetComponent<SpriteRenderer>().sprite;
hit.transform.gameObject.tag = "ok";
CmdclientPlaying();
}
else if (hit && hit.transform.gameObject.tag.Equals("Untagged") && !localTurn)
{
hit.transform.gameObject.GetComponent<SpriteRenderer>().sprite = redBar.GetComponent<SpriteRenderer>().sprite;
hit.transform.gameObject.tag = "ok";
CmdlocalPlaying();
}
when the CmdclientPlaying(); is called it makes the localTurn to false which will trigger the next if statement and make call to CmdlocalPlaying()

i changed the code . i call the function to change the bool outside Rpcclick()
and it worked .
but i dont now why it does not work before .

Related

Is there a way to make a game object pause whenever touching another game object? on c# from unity?

So I am trying to find a way to make a player move infinitely just by clicking the right arrow key ones and if it touches another game object it stops at the game objects postion and if button clicked again it moves again.
Note: I just started using unity also just started programming in c# so please try to explain things in an easy and understanding way.
Heres the code:
Rigidbody2D rb2d;
public float speed = 10;
public const string RIGHT = "right";
public const string LEFT = "left";
string buttonPressed;
public GameObject Rainbow_1;
public GameObject Rainbow_0;
bool isCol = false;
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
if (Input.GetKey(KeyCode.RightArrow)) { buttonPressed = RIGHT; }
else if (Input.GetKey(KeyCode.LeftArrow)) { buttonPressed = LEFT; }
else { buttonPressed = null; }
}
private void FixedUpdate()
{
if(buttonPressed == RIGHT)
{
if(isCol)
{
StartCoroutine(sfos());
}
else if(!isCol)
{
rb2d.velocity = new Vector2(speed, 0);
}
}
}
IEnumerator sfos()
{
Rainbow_0.transform.position = Rainbow_1.transform.position;
yield return new WaitForSeconds(3);
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("Collision detected");
isCol = isCol;
}
private void OnCollisionExit2D(Collision2D other) { isCol = !isCol; }
What you want to do is stop your player:
rb2d.velocity = new Vector2(0, 0);
You also need to signal a collision:
isCol = true;
Collision
You're not setting your isCol variable to true at any point outside of initialization. This means that your first collision will register, but all subsequent collisions will not; to fix this, change:
private void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Collision detected");
isCol = isCol;
}
private void OnCollisionExit2D(Collision2D other) { isCol = !isCol; }
To:
private void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Collision detected");
isCol = true;
}
private void OnCollisionExit2D(Collision2D other) { isCol = false; }
It's easier to see when it's explicit like this.
Velocity
For velocity, your FixedUpdate method is conditionally setting the velocity to speed, 0, but you never set it to anything else:
private void FixedUpdate() {
if(buttonPressed == RIGHT) {
if(isCol) {
StartCoroutine(sfos());
}
else if(!isCol) {
rb2d.velocity = new Vector2(speed, 0);
}
}
}
You need to set your velocity to zero if you're not supposed to be moving; so if isCol is true:
private void FixedUpdate() {
if(buttonPressed == RIGHT) {
if(isCol) {
rb2d.velocity = new Vector2(0, 0);
StartCoroutine(sfos());
}
else if(!isCol) {
rb2d.velocity = new Vector2(speed, 0);
}
}
}
Additionally, for simplicity's sake, I believe Unity's 2D vector contains a property/field named zero, so the following may also work, but without direct access to Unity at the moment I won't promise anything. 🙃
rb2d.velocity = Vector2.zero

First Person Shooter box collider problem

I'm creating a FPS game and I have the following issue:
Sometimes, when I shoot at the enemies the hit is not recognized, even if the player is shooting in front of them. However, when they attack the player, the hit is recognized normally.
They have a box collider and a rigidbody attached to them.
This script is attached to the player:
using System.Collections.Generic;
using UnityEngine;
public class DisparaArma : MonoBehaviour
{
private GerenciaArma gerenciaArma;
public float nDisparo = 15f;
private float TempoProximoDisparo;
public float damage = 20f;
private Animator ZoomCameraIn;
private bool zoomed;
private Camera Maincamera;
private GameObject mira;
// Start is called before the first frame update
void Start()
{
gerenciaArma = GetComponent<GerenciaArma>();
ZoomCameraIn = transform.Find(Tags.LOOK_ROOT).transform.Find(Tags.ZOOM_CAMERA).GetComponent<Animator>();
mira = GameObject.FindWithTag(Tags.MIRA);
Maincamera = Camera.main;
}
// Update is called once per frame
void Update()
{
Atira();
ZoomInAndOut();
}
void Atira()
{
if (Input.GetMouseButtonDown(0))
{
if(gerenciaArma.SelecionaArma().tipoBala == WeaponBulletType.BULLET)
{
gerenciaArma.SelecionaArma().AnimacaoTiro();
DisparaBala();
}
}
}
void ZoomInAndOut()
{
if (gerenciaArma.SelecionaArma().mira_tipo == TipoMira.AIM)
{
if (Input.GetMouseButtonDown(1))
{
ZoomCameraIn.Play(Animacoes.ZOOM_IN_ANIM);
// gerenciaArma.SelecionaArma().Aim(true);
mira.SetActive(false);
print("VaiZoom");
}
if (Input.GetMouseButtonUp(1))//
{
ZoomCameraIn.Play(Animacoes.ZOOM_OUT_ANIM);
//gerenciaArma.SelecionaArma().Aim(false);
mira.SetActive(true);
}
}
}
void DisparaBala()
{
RaycastHit hit;
if(Physics.Raycast(Maincamera.transform.position, Maincamera.transform.forward, out hit))
{
if (hit.transform.tag == Tags.ENEMY_TAG)
{
hit.transform.GetComponent<ScriptVida>().DanoAplicado(damage);
}
}
}
}
And this one is attached to the enemies:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class ScriptVida : MonoBehaviour
{
private IndioAnimações indio_Anim;
private NavMeshAgent navAgent;
private IndioController indio_Controller;
public float vida = 100f;
public bool is_Player, is_Cannibal, is_Tiger;
private bool morto;
// Start is called before the first frame update
void Awake()
{
if (is_Tiger || is_Cannibal)
{
indio_Anim = GetComponent<IndioAnimações>();
indio_Controller = GetComponent<IndioController>();
navAgent = GetComponent<NavMeshAgent>();
}
if (is_Player)
{
}
}
public void DanoAplicado(float damage)
{
if (morto)
return;
vida -= damage;
if (is_Player)
{
}
if (is_Tiger || is_Cannibal)
{
if (indio_Controller.EnemyState == EnemyState.PATROL)
{
indio_Controller.chase_Distance = 50f;
}
}
if (vida <= 0)
{
JogadorMorre();
morto = true;
print(vida);
}
}
void JogadorMorre()
{
if (is_Cannibal)//
{
GetComponent<Animator>().enabled = false;
GetComponent<BoxCollider>().isTrigger = false;
GetComponent<Rigidbody>().AddTorque(-transform.forward * 50f);
indio_Controller.enabled = false;
navAgent.enabled = false;
indio_Anim.enabled = false;
}
if (is_Tiger)
{
GetComponent<Animator>().enabled = false;
GetComponent<BoxCollider>().isTrigger = false;
GetComponent<Rigidbody>().AddTorque(-transform.forward * 50f);
indio_Controller.enabled = false;
navAgent.enabled = false;
indio_Anim.enabled = false;
}
if (is_Player)
{
GameObject[] enemies = GameObject.FindGameObjectsWithTag(Tags.ENEMY_TAG);
for (int i = 0; i < enemies.Length; i++)
{
enemies[i].GetComponent<IndioController>().enabled = false;
}
GetComponent<Movimentação>().enabled = false;
GetComponent<DisparaArma>().enabled = false;
GetComponent<GerenciaArma>().SelecionaArma().gameObject.SetActive(false);
}
if (tag == Tags.PLAYER_TAG)
{
Invoke("RestartGame", 3f);
}
else
{
Invoke("TurnOffGameObject", 3f);
}
}
void RestartGame()
{
UnityEngine.SceneManagement.SceneManager.LoadScene("Gameplay");
}
void TurnOffGameObject()
{
gameObject.SetActive(false);
}
}
I think the problem is related to the box collider.
How could I solve this guys?

How to send commands on NON-Player Gameobjects in Unity

I am unable to send commands from my gun prefabs in my game. How can I send commands from non-player game objects? Every time I try to send a command, I get an error. I do not want to move my shooting scripts from my guns to my player, as this method will require me to change my game drastically.
My Shooting Script:
[Command]
void CmdOpenFire(){
if (Physics.Raycast(camTransform.TransformPoint(startPosition), camTransform.forward, out hit, range)){
gunsMasterScript.CallEventShotDefault(hit.point, hit.transform);
if (hit.transform.parent != null) {
if (hit.transform.parent.CompareTag ("Enemy")) {
gunsMasterScript.CallEventShotEnemy (hit.point, hit.transform.parent);
}
}
if (hit.transform.tag == "Player") {
gunsMasterScript.CallEventShotEnemy (hit.point, hit.transform);
}
}
}
My shooting Detection script:
public PlayerManager_AmmoBox localPlayerTester;
public GunsManager_GunsAmmo gunsAmmo;
public GunsManager_GunsMaster gunMaster;
float nextAttack;
public float attackRate = 0.5f;
Transform myTransform;
public bool isAutomatic = true;
public bool hasBurstFire;
bool isBurstFireActive;
public string attackButtonName;
public string reloadButtonName;
public string burstFireButtonName;
NetworkIdentity netID;
// Use this for initialization
void OnEnable () {
if (transform.root != null) {
if (transform.root.GetComponent<PlayerManager_AmmoBox> () != null) {
localPlayerTester = transform.root.GetComponent<PlayerManager_AmmoBox> ();
}
}
SetInitialReferences ();
}
// Update is called once per frame
void Update () {
if (localPlayerTester != null) {
CheckIfWeaponShouldAttack ();
CheckForReloadRequest ();
CheckForBurstFireToggle ();
}
}
void SetInitialReferences(){
netID = GetComponent<NetworkIdentity> ();
myTransform = transform;
gunMaster = transform.GetComponent<GunsManager_GunsMaster> ();
gunsAmmo = transform.GetComponent<GunsManager_GunsAmmo> ();
gunMaster.isGunLoaded = true;
}
void CheckIfWeaponShouldAttack(){
if (gunMaster != null) {
if (Time.time > nextAttack && Time.timeScale > 0 && myTransform.root.CompareTag ("Player") && gunMaster.isGunLoaded) {
if (isAutomatic && !isBurstFireActive) {
if (Input.GetButton (attackButtonName)) {
AttemptAttack ();
}
} else if (isAutomatic && isBurstFireActive) {
if (Input.GetButtonDown (attackButtonName)) {
StartCoroutine (RunBurstFire ());
}
} else if (!isAutomatic) {
if (Input.GetButton (attackButtonName)) {
AttemptAttack ();
}
}
}
}
}
void AttemptAttack(){
nextAttack = Time.time + attackRate;
if (gunMaster.isGunLoaded) {
gunMaster.CallEventPlayerInput ();
} else {
gunMaster.CallEventGunNotUsable ();
}
}

In Unity3d, How to detect touch on UI, or not?

I am making a Unity3d mobile application. And I have a problem: How to detect touch on UI, or not?
I tried this (but it doesn't work):
UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject();
and this:
private static List<RaycastResult> tempRaycastResults = new List<RaycastResult>();
public bool PointIsOverUI(float x, float y)
{
var eventDataCurrentPosition = new PointerEventData(EventSystem.current);
eventDataCurrentPosition.position = new Vector2(x, y);
tempRaycastResults.Clear();
EventSystem.current.RaycastAll(eventDataCurrentPosition, tempRaycastResults);
return tempRaycastResults.Count > 0;
}
For mobile you need to pass the id of the Touch to IsPointerOverGameObject
foreach (Touch touch in Input.touches)
{
int id = touch.fingerId;
if (EventSystem.current.IsPointerOverGameObject(id))
{
// ui touched
}
}
Please try this :
// for Android check differently :
if(EventSystem.current.IsPointerOverGameObject(0) return false;
// for windows check as usual :
if (EventSystem.current.IsPointerOverGameObject())
return false;
Add this to the clickable object
private MyUIHoverListener uiListener;
private Vector3 mousePos;
private void OnMouseDown()
{
mousePos = Input.mousePosition;
Debug.Log(Input.mousePosition);
}
private void OnMouseUp()
{
//this part helps to not trigger object when dragging
mousePos -= Input.mousePosition;
//Debug.Log(mousePos);
if(mousePos.x < 3 && mousePos.y < 3
&& mousePos.z < 3 && mousePos.x > -3
&& mousePos.y > -3 && mousePos.z > -3)
{
//Debug.Log("NOT MOVED");
if (!GameMan.ObjectClickBlocker)
{
if (uiListener.IsUIOverride)
{
//Debug.Log("Cancelled OnMouseDown! A UI element has override this object!");
}
else
{
// Debug.Log("Object OnMouseDown");
StartCoroutine(LoadThisBuilding(0));
ToggleBuildingMenu();
}
}
}
}
Add this on the object in front of the clickable object:
public class MyUIHoverListener : MonoBehaviour
{
[SerializeField]
public bool IsUIOverride { get; private set; }
void Update()
{
// It will turn true if hovering any UI Elements
IsUIOverride = EventSystem.current.IsPointerOverGameObject();
}
void OnDisable()
{
IsUIOverride = false;}
}
}

Unity: Need help how to double click detection in c#?

I wanna create mouse click that detect single click, hold click, and double click.
When I do single click, the character will faster (moveSpeed = 15), when I hold click and double click there is no action, the character still constant with it speed (moveSpeed = 3).
Here is my code:
private float t0, moveSpeed;
private bool longClick, shortClick;
void Start ()
{ t0 = 0f; longClick = false; shortClick = false; }
void update()
{
// how to add the code for detect double click and where I write it?
if (Input.GetMouseButtonDown (0))
{
t0 = 0; t0 += Time.deltaTime;
longClick = false; shortClick = false;
moveSpeed = 0;
}
if (Input.GetMouseButton(0))
{
t0 += Time.deltaTime;
if (t0 < 0.2)
{ moveSpeed = 15;longClick = false; shortClick = true; } // this is single click!
if (t0 > 0.2)
{ moveSpeed = 3; longClick = true; shortClick = false; } // this is hold click!
}
if (Input.GetMouseButtonUp(0))
{
if (longClick == true)
{ moveSpeed = 3; }
else if (shortClick = true)
{ moveSpeed = 3; }
}
}
Have you tried googling? - See the second answer here: http://answers.unity3d.com/questions/331545/double-click-mouse-detection-.html
In C#:
private float lastClickTime;
public float catchTime = 0.25f;
void Update ()
{
if(Input.GetButtonDown("Fire1"))
{
if(Time.time - lastClickTime < catchTime)
{
//double click
print("Double click");
}
else
{
//normal click
}
lastClickTime = Time.time;
}
}
I replied here: http://answers.unity3d.com/answers/1133702/view.html
Basically: create a new class with the doubleClicked checker inside. Then use it in an if clause.
class DoubleClickListener {
bool firstClick = false;
float runningTimerSecond;
float delay = 0.25F;
public DoubleClickListener() { }
public DoubleClickListener(float delay) {
this.delay = delay;
}
public bool isDoubleClicked() {
// If the time is too long we reset first click variable
if (firstClick && (Time.time - runningTimerSecond) > delay) {
firstClick = false;
}
if (!firstClick) {
firstClick = true;
runningTimerSecond = Time.time;
} else {
firstClick = false;
return true;
}
return false;
}
}
DoubleClickBehaviorBase is a base class that will take care of double click for you.
You inherit from DoubleClickBehaviorBase instead of MonoBehavior
All you need to do is override OnDoubleClickOverride in your class.
I've also included a MonoBehaviourExtension that makes it easier to call and
implement StartCoroutine:
namespace DoubleClick
{
public static class MonoBehaviourExtension
{
public static void StartCoroutine(this MonoBehaviour mb, params Action[] funcs)
{
mb.StartCoroutine(CoroutineRunnerSimple(funcs));
}
private static System.Collections.IEnumerator CoroutineRunnerSimple(Action[] funcs)
{
foreach (var func in funcs)
{
if (func != null)
func();
yield return new WaitForSeconds(.01f);
}
}
}
abstract public class DoubleClickBehaviorBase : MonoBehaviour
{
float _DoubleClickTimer = 0.0f;
float _DoubleClickDelay = 0.5f;
bool _WasClicked = false;
// Update is called once per frame
protected virtual void Update()
{
// this starts timing when a click occurs
//
if (this._WasClicked == true)
{
this._DoubleClickTimer += Time.deltaTime;
}
// this must be in update because it expires based on time and not clicks
//
if (this._DoubleClickTimer > this._DoubleClickDelay)
{
this._WasClicked = false;
this._DoubleClickTimer = 0.0f;
}
}
protected virtual void OnMouseDoubleClick()
{
}
protected virtual void OnMouseDown()
{
if (this._WasClicked == false && this._DoubleClickTimer < _DoubleClickDelay)
{
this._WasClicked = true;
}
else if (this._WasClicked == true &&
this._DoubleClickTimer < this._DoubleClickDelay)
{
this.StartCoroutine(() => this.OnMouseDoubleClick());
}
}
}
}

Categories

Resources