i already make the player character to move to it is destination (animate the character to move to that destination), i wanted to disable the GUI button when the player character is moving, but i can't get it and work it out. Could you guys help me?
Here is the code:
public class UserPlayer : Player
{
public override void TurnUpdate()
{
//Moving animation
if (positionQueue.Count > 0)
{
GUI.enabled = false; // This is the one that i want when the character still moving (animation still moving), disabled the GUI. But i can't get it
transform.position += (positionQueue[0] - transform.position).normalized * moveSpeed * Time.deltaTime;
if (Vector3.Distance(positionQueue[0], transform.position) <= 0.1f)
{
transform.position = positionQueue[0];
positionQueue.RemoveAt(0);
if (positionQueue.Count == 0)
{
actionPoints--;
}
}
}
base.TurnUpdate();
}
public override void TurnOnGUI()
{
base.TurnOnGUI();
}
}
public class Player : MonoBehaviour
{
//for movement animation
public List<Vector3> positionQueue = new List<Vector3>();
public virtual void TurnUpdate()
{
if (actionPoints <= 0)
{
actionPoints = 2;
magicAttacking = false;
moving = false;
attacking = false;
GameManager.instance.NextTurn();
}
}
public virtual void TurnOnGUI()
{
if (GameManager.instance.currentPlayerIndex == 0 || GameManager.instance.currentPlayerIndex == 2)
{
//ToolTip Text
move = GUI.Button(buttonRect, new GUIContent("Move", "Move the Player"));
GUI.Label(tooltipRect, GUI.tooltip, label1);
GUI.tooltip = null;
//Move Button
if (move)
{
if (!moving)
{
GameManager.instance.RemoveTileHighlights();
moving = true;
attacking = false;
GameManager.instance.HighlightTilesAt(gridPosition, Color.blue, movementPerActionPoint);
}
else
{
moving = false;
attacking = false;
GameManager.instance.RemoveTileHighlights();
}
}
}
Your question has been already made, take a look here.
Adapt your code in this way:
public virtual void TurnOnGUI() {
if (GameManager.instance.currentPlayerIndex == 0 || GameManager.instance.currentPlayerIndex == 2) {
...
if(!moving) {
move = GUI.Button(buttonRect, new GUIContent("Move", "Move the Player"));
GUI.Label(tooltipRect, GUI.tooltip, label1);
}
...
}
}
Related
I wanted to add multiplayer to my game but i quickly faced many many problems, i cant find any clear solution online. i made a weapon script where the player can shoot and reload.
problems:
when i shoot, on 1 screen both players shoot, but at the other screen nothing happens
when i swap weapons, on 1 screen both players swap weapons, on the second screen nothing happens
note: im still a complete beginner so go easy on me please :)) thanks!
weapon script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Photon.Pun;
public class weaponScript : MonoBehaviour
{
public weaponSO weaponStats;
public GameObject reloadingText;
public TMP_Text ammoValue;
public Transform firePoint;
public GameObject bulletPrefab;
public float bulletForce = 2f;
public bool isShooting;
public float pistolDamage;
public int currentAmmoClip = 1;
public int maxAmmoClip;
public int currentReserve = 1;
public int maxReserve;
public float reloadTime = 2f;
public bool isReloading = false;
public int bulletsShot;
public float startingDamage;
PhotonView view;
public void Start()
{
view = GetComponent<PhotonView>();
if(view.IsMine)
{
view.RPC("Update", RpcTarget.AllBuffered);
}
WeaponStats();
currentAmmoClip = maxAmmoClip;
currentReserve = maxReserve;
bulletsShot = maxAmmoClip - currentAmmoClip;
isShooting = false;
weaponStats.damage = startingDamage;
}
[PunRPC]
public void Update()
{
ammoValue.text = currentAmmoClip.ToString("0") + "/" + currentReserve.ToString("0");
if (Input.GetKeyDown(KeyCode.R))
{
if(currentReserve <= 0)
{
return;
}
if (currentAmmoClip == maxAmmoClip && !isReloading)
{
return;
}
else
{
StartCoroutine(Reload());
return;
}
}
if(Input.GetButtonDown("Fire1") && currentAmmoClip >= 1)
{
if(isReloading == false)
{
bulletsShot += 1;
currentAmmoClip -= 1;
isShooting = true;
Shoot();
FindObjectOfType<AudioManager>().Play("shot1");
return;
}
}
if(isReloading)
return;
if(currentAmmoClip <= 0 && currentReserve >= 1)
{
StartCoroutine(Reload());
return;
}
}
IEnumerator Reload()
{
reloadingText.SetActive(true);
isReloading = true;
yield return new WaitForSeconds(reloadTime);
if(currentReserve <= bulletsShot)
{
currentAmmoClip += currentReserve;
currentReserve = 0;
}
else
{
currentReserve -= bulletsShot;
currentAmmoClip = maxAmmoClip;
}
bulletsShot = 0;
reloadingText.SetActive(false);
isReloading = false;
}
void Shoot()
{
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
public void WeaponStats()
{
pistolDamage = weaponStats.initialDamage;
maxAmmoClip = weaponStats.maxAmmoClip;
maxReserve = weaponStats.maxReserve;
reloadTime = weaponStats.reloadTime;
bulletForce = weaponStats.bulletForce;
startingDamage = weaponStats.initialDamage;
}
}
weapon holder:
using UnityEngine;
public class WeaponHolder : MonoBehaviour
{
public int selectedWeapon = 0;
void Start()
{
SelectWeapon();
}
void Update()
{
if(FindObjectsOfType<weaponScript>()[0].isReloading == true)
{
return;
}
else
{
switchWeapon();
}
}
public void switchWeapon()
{
int previousSelectedWeapon = selectedWeapon;
if(Input.GetAxis("Mouse ScrollWheel") > 0f)
{
if(selectedWeapon >= transform.childCount - 1)
{
selectedWeapon = 0;
}
else
{
selectedWeapon++;
}
}
if(Input.GetAxis("Mouse ScrollWheel") < 0f)
{
if(selectedWeapon <= 0)
{
selectedWeapon = transform.childCount - 1;
}
else
{
selectedWeapon--;
}
}
if(previousSelectedWeapon != selectedWeapon)
{
SelectWeapon();
}
}
public void SelectWeapon()
{
int i = 0;
foreach (Transform weapon in transform)
{
if(i == selectedWeapon)
{
weapon.gameObject.SetActive(true);
}
else
{
weapon.gameObject.SetActive(false);
}
i++;
}
}
}
i tried adding
if(view.IsMine == true)
{
Debug.Log("true");
}
else
{
Debug.Log("false");
}
but nothing happened and i couldnt shoot anymore. thanks for reading
The problem is you don't sync anything in your game. This means the other computer can't know what it has to do.
Whenever you want to sync something you have to call an RPC function.
Maybe watch some tutorials about how to do this properly and how to set up a simple multiplayer lobby.
EDIT:
What the other comments above mentioned with .IsMine is true, but you're doing it wrong. You have to call this in start or awake and whenever the view is not yours you disable the camera of the person only and disable shooting. Its important to only do this on your computer! If you are not doing everyone will shoot when you press Shoot and everyone will walk when you walk.
I have a script for gun switching, it have an array to get the MeshRenderer component of all elements, then, i can enable the element that i want, but i cannot disable the others.
public class TrocarArma : MonoBehaviour
{
[Header("References")]
public int choosenGun = 0;
[Space(10)]
[SerializeField] MeshRenderer[] meshes = new MeshRenderer[4];
void Start()
{
SelectWeapon();
}
void Update()
{
ChangeGun();
}
void SelectWeapon()
{
int gunCount = 0;
meshes[0] = GameObject.Find("GravityGun").GetComponent<MeshRenderer>();
meshes[1] = GameObject.Find("IronBar").GetComponent<MeshRenderer>();
meshes[2] = GameObject.Find("Tablet").GetComponent<MeshRenderer>();
meshes[3] = null; //Will be filled later.
foreach(Transform gun in transform)
{
if (gunCount == choosenGun)
{
meshes[choosenGun].enabled = true;
}
else
{
///Code to make the others array meshes elements MeshRenderers disable.
}
gunCount++;
}
}
void ChangeGun()
{
int previousWeapon = choosenGun;
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if(choosenGun >= transform.childCount -1)
{
choosenGun = 0;
}
else
{
choosenGun++;
}
}
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (choosenGun <= 0)
{
chooseGun = transform.childCount - 1;
}
else
{
chooseGun--;
}
}
if (previousWeapon != chooseGun)
{
SelectWeapon();
}
}
}
I simply not used SetActive(true)/(false) because I need my tablet active to upgrade my defenses. The video that i make this script: https://www.youtube.com/watch?v=Dn_BUIVdAPg , thanks for reading!
You have strange logic inside void SelectWeapon() method. But, I dare to suggest that the following code can help you:
foreach(Transform gun in transform)
{
if (gunCount == choosenGun)
{
meshes[choosenGun].enabled = true;
}
else
{
meshes[gunCount].enabled = false;
}
gunCount++;
}
or
foreach(Transform gun in transform)
{
switch(gunCount)
{
case 0:
meshes[choosenGun].enabled = true;
break;
default:
meshes[gunCount].enabled = false;
break;
}
gunCount++;
}
By the way:
meshes[3] = null; will throw an exception when you try to access the .enabled property. It is better not to allow such null elements, or always to check for null.
I am working on a 2D, topdown, roguelike game but i got stuck when i tried to make a shooting system.
when i run it and press the arrow keys, the bullet spawns and points in the right direction. It juste doesn't move in any way.
This is my code and i hope someone can figure it out. Btw, everything is connected. The player and the bullet prefab.
using System.Collections;
using System.Linq;
using UnityEngine;
namespace Assets.Scripts
{
[RequireComponent(typeof(Player))]
public class PlayerShootController : ShootControllerBase
{
[SerializeField]
private int _numberOfBombs;
public int NumberofBombs
{
get { return _numberOfBombs; }
set { _numberOfBombs = value; }
}
[SerializeField]
private PlayerHeadController _headObject;
public PlayerHeadController HeadObject
{
get { return _headObject; }
set { _headObject = value; }
}
[SerializeField]
private Bomb _bombPrefab;
public Bomb BombPrefab
{
get { return _bombPrefab; }
set { _bombPrefab = value; }
}
public bool IsShooting { get; private set; }
private KeyCode _shootKey;
private Vector2 _shootDirection;
private Player _player;
public override void Start()
{
base.Start();
_player = GetComponent<Player>();
}
public override void Update()
{
base.Update();
if (IsShooting)
{
SetHeadDirection(_shootKey);
return;
}
if (InputHelpers.IsAnyKey(KeyCode.UpArrow, KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow))
{
if (Input.GetKey(KeyCode.UpArrow))
{
_shootDirection = new Vector2(0, BulletSpeed);
_shootKey = KeyCode.UpArrow;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
_shootDirection = new Vector2(0, -BulletSpeed);
_shootKey = KeyCode.DownArrow;
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
_shootDirection = new Vector2(-BulletSpeed, 0);
_shootKey = KeyCode.LeftArrow;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
_shootDirection = new Vector2(BulletSpeed, 0);
_shootKey = KeyCode.RightArrow;
}
StartCoroutine(Shoot());
}
if (NumberofBombs > 0 && InputHelpers.IsAnyKeyDown(KeyCode.LeftShift, KeyCode.RightShift, KeyCode.E))
{
var bomb = (Bomb) Instantiate(BombPrefab);
bomb.transform.position = transform.position;
NumberofBombs--;
}
}
IEnumerator Shoot()
{
IsShooting = true;
while (Input.GetKey(_shootKey))
{
var bullet = (Rigidbody2D)Instantiate(BulletPrefab);
bullet.GetComponent<BulletScript>().Shooter = transform.gameObject;
bullet.transform.position = transform.position;
if (_shootDirection.y > 0)
{
bullet.transform.Rotate(0, 0, -90);
}
else if (_shootDirection.y < 0)
{
bullet.transform.Rotate(0, 0, 90);
}
else if (_shootDirection.x > 0)
{
TransformHelpers.FlipX(bullet.gameObject);
}
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
if (ShootClips.Any())
{
var clipToPlay = ShootClips[Random.Range(0, ShootClips.Count)];
clipToPlay.pitch = Random.Range(MinShootPitch, MaxShootPitch);
clipToPlay.Play();
}
yield return new WaitForSeconds(ShootingSpeed);
}
IsShooting = false;
//Reset head flipping
if (_headObject.transform.localScale.x < 0)
{
TransformHelpers.FlipX(_headObject.gameObject);
}
}
private void SetHeadDirection(KeyCode shootKey)
{
switch (shootKey)
{
case KeyCode.UpArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Up);
break;
case KeyCode.DownArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Down);
break;
case KeyCode.LeftArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Left);
break;
case KeyCode.RightArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Right);
break;
}
}
}
}
try this:
bullet.AddForce(_shootDirection*moveSpeed*Time.deltaTime);
instead of this:
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
tweak the speed for desired result, and if you want the bullet to follow the player you will need to update the shoot direction every certain time with a couroutine
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;}
}
}
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());
}
}
}
}