Unity: Need help how to double click detection in c#? - 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());
}
}
}
}

Related

How do I know when the fading coroutine is over when fading out or in?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fading : MonoBehaviour
{
[Header("Fading")]
public List<GameObject> objectsToFade = new List<GameObject>();
public float duration;
public Coroutine fadeCoroutine;
public bool automatic = false;
public bool startFading = false;
[Header("Random")]
public bool randomObjects = false;
public bool randomDuration = false;
public bool faded = false;
private bool fadeInOut = false;
private bool coroutineIsRunning = false;
private List<Material> objectsToFadeMaterials = new List<Material>();
private bool randomOnce = false;
private Material randomMaterial;
private float originalDuration;
private void Start()
{
originalDuration = duration;
for (int i = 0; i < objectsToFade.Count; i++)
{
objectsToFadeMaterials.Add(objectsToFade[i].GetComponent<Renderer>().material);
}
}
private void Update()
{
if (startFading)
{
if (automatic)
{
if (!coroutineIsRunning)
{
Fade();
}
}
else
{
if (Input.GetKeyDown(KeyCode.G))
{
Fade();
}
}
}
}
private void Fade()
{
fadeInOut = !fadeInOut;
if (fadeCoroutine != null)
StopCoroutine(fadeCoroutine);
if(randomDuration)
{
duration = Random.Range(1, 20);
}
else
{
duration = originalDuration;
}
if (randomObjects && objectsToFade.Count > 1)
{
if (randomOnce == false)
{
randomMaterial = objectsToFadeMaterials[Random.Range(0, objectsToFadeMaterials.Count)];
randomOnce = true;
}
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 1, duration));
}
}
else
{
for (int i = 0; i < objectsToFadeMaterials.Count; i++)
{
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 1, duration));
}
}
}
}
public IEnumerator FadeTo(Material material, float targetOpacity, float duration)
{
Color color = material.color;
float startOpacity = color.a;
float t = 0;
coroutineIsRunning = true;
while (t < duration)
{
t += Time.deltaTime;
float blend = Mathf.Clamp01(t / duration);
color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);
material.color = color;
if(t > duration)
{
coroutineIsRunning = false;
}
if(color.a == 1)
{
randomOnce = false;
}
if(color.a == 0)
{
faded = true;
}
yield return null;
}
}
}
I know that if the color.a is 0 then the object faded out finished then I set faded to true.
In the second script that is attached to a teleporter I want to start teleporting if the object faded out then teleport to the next teleporter and fade in back and so on.
This script is attached to each teleporter :
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Fading fading;
public List<GameObject> objectsToTeleport = new List<GameObject>();
//Start is called before the first frame update
void Start()
{
objectsToTeleport = GameObject.FindGameObjectsWithTag("ObjectToTeleport").ToList();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeTo(objectsToTeleport[0].GetComponent<Renderer>().material, 0, 2));
}
}
and this script is the teleporting script :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net.WebSockets;
using UnityEngine;
using UnityEngine.Scripting.APIUpdating;
public class Teleporting : MonoBehaviour
{
public List<ObjectToTeleport> objectsToTeleport;
public List<ObjectToTeleport> currentlyTeleportedObjects;
public List<GameObject> teleporters;
public float teleportingTime;
public float teleportingStartTime;
public bool startTeleporting = false;
public GameObject[] groups;
public bool loop = false;
public bool random = false;
public int teleportationsCount = 0;
[Serializable]
public class ObjectToTeleport
{
public GameObject teleportableObject;
public int teleportOrder;
}
public void Start()
{
StartTeleporting();
}
private void Update()
{
}
public void StartTeleporting()
{
if (startTeleporting)
{
if (teleporters.Count > 1 && objectsToTeleport.Count > 0)
{
InvokeRepeating("MoveTeleportableObjects", teleportingStartTime, teleportingTime);
}
}
}
private void MoveTeleportableObjects()
{
if (teleportationsCount < objectsToTeleport.Count)
currentlyTeleportedObjects.Add(objectsToTeleport[teleportationsCount]);
for (int i = 0; i < currentlyTeleportedObjects.Count; i++)
{
if (!loop)
{
MoveObjects(i);
}
else
{
MoveObjects(i);
}
}
teleportationsCount++;
}
private void MoveObjects(int i)
{
GameObject destinationTeleporter = teleporters[currentlyTeleportedObjects[i].teleportOrder];
currentlyTeleportedObjects[i].teleportableObject.transform.position = destinationTeleporter.transform.position;
if (currentlyTeleportedObjects[i].teleportOrder < teleporters.Count - 1)
{
currentlyTeleportedObjects[i].teleportOrder++;
}
else if (loop == true)
{
{
currentlyTeleportedObjects[i].teleportOrder = 0;
}
}
}
}
I need somehow a synchronization between the fading and the teleporting in the Teleport script.
But it seems a bit complicated.
The Fading script on it's own and the Teleporting script on it's own are working fine but making a synchronization between them is the problem.
Update :
What I tried :
In the Fading script I added two methods FadIn and FadeOut and calling the FadeOut in the Teleport script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fading : MonoBehaviour
{
[Header("Fading")]
public List<GameObject> objectsToFade = new List<GameObject>();
public float duration;
public Coroutine fadeCoroutine;
public bool automatic = false;
public bool startFading = false;
[Header("Random")]
public bool randomObjects = false;
public bool randomDuration = false;
public bool faded = false;
private bool fadeInOut = false;
private bool coroutineIsRunning = false;
private List<Material> objectsToFadeMaterials = new List<Material>();
private bool randomOnce = false;
private Material randomMaterial;
private float originalDuration;
private void Start()
{
originalDuration = duration;
for (int i = 0; i < objectsToFade.Count; i++)
{
objectsToFadeMaterials.Add(objectsToFade[i].GetComponent<Renderer>().material);
}
}
private void Update()
{
if (startFading)
{
if (automatic)
{
if (!coroutineIsRunning)
{
Fade();
}
}
else
{
if (Input.GetKeyDown(KeyCode.G))
{
Fade();
}
}
}
}
private void Fade()
{
fadeInOut = !fadeInOut;
if (fadeCoroutine != null)
StopCoroutine(fadeCoroutine);
if(randomDuration)
{
duration = Random.Range(1, 20);
}
else
{
duration = originalDuration;
}
if (randomObjects && objectsToFade.Count > 1)
{
if (randomOnce == false)
{
randomMaterial = objectsToFadeMaterials[Random.Range(0, objectsToFadeMaterials.Count)];
randomOnce = true;
}
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(randomMaterial, 1, duration));
}
}
else
{
for (int i = 0; i < objectsToFadeMaterials.Count; i++)
{
if (fadeInOut)
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 0, duration));
}
else
{
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 1, duration));
}
}
}
}
private IEnumerator FadeTo(Material material, float targetOpacity, float duration)
{
Color color = material.color;
float startOpacity = color.a;
float t = 0;
coroutineIsRunning = true;
while (t < duration)
{
t += Time.deltaTime;
float blend = Mathf.Clamp01(t / duration);
color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);
material.color = color;
if(t > duration)
{
coroutineIsRunning = false;
}
if(color.a == 1)
{
randomOnce = false;
}
yield return null;
}
}
public IEnumerator FadeIn(Material material, float duration)
{
StartCoroutine(FadeTo(material, 1, duration));
yield return new WaitForSeconds(duration);
}
public IEnumerator FadeOut(Material material, float duration)
{
StartCoroutine(FadeTo(material, 0, duration));
yield return new WaitForSeconds(duration);
}
}
In the Teleport script
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Teleport : MonoBehaviour
{
public Fading fading;
public List<GameObject> objectsToTeleport = new List<GameObject>();
//Start is called before the first frame update
void Start()
{
objectsToTeleport = GameObject.FindGameObjectsWithTag("ObjectToTeleport").ToList();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3));
}
private void OnTriggerExit(Collider other)
{
}
}
How do I continue from here ? what should I do next ?
There are multiple ways.
Simply yield the routine
You already have both as Coroutines so you could wrap them in another Coroutine and yield return it instead of StartCoroutine (this is something you should do in FadeIn and FadeOut anyway!)
// If this returns IEnumerator Unity automatically runs it as Coroutine
private IEnumerator OnTriggerEnter(Collider other)
{
yield return fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3));
// Something after fading finished
Debug.Log("Fade Out finished!");
}
You could of course as well have them separately like
private void OnTriggerEnter(Collider other)
{
StartCorouine (EnterRoutine(other));
}
private IEnumerator EnterRoutine ()
{
yield return fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3));
// Something after fading finished
Debug.Log("Fade Out finished!");
}
Callback
Another way would be passing in a callback that is executed once the routine finishes like e.g.
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3, OnFadeOutFinished));
}
private void OnFadeOutFinished ()
{
Debug.Log("Fade Out finished!", this);
}
or using a lambda, especially helpful if you want to do something with the other reference
private void OnTriggerEnter(Collider other)
{
StartCoroutine(fading.FadeOut(objectsToTeleport[0].GetComponent<Renderer>().material, 3, () => {
Debug.Log("Fade Out finished!");
}));
}
and have it as parameter in your routine like
private IEnumerator FadeTo(Material material, float targetOpacity, float duration, Action callback)
{
Color color = material.color;
float startOpacity = color.a;
float t = 0;
coroutineIsRunning = true;
while (t < duration)
{
t += Time.deltaTime;
float blend = Mathf.Clamp01(t / duration);
color.a = Mathf.Lerp(startOpacity, targetOpacity, blend);
material.color = color;
if(t > duration)
{
coroutineIsRunning = false;
}
if(color.a == 1)
{
randomOnce = false;
}
yield return null;
}
callback?.Invoke();
}
public IEnumerator FadeIn(Material material, float duration, Action callback = null)
{
yield return FadeTo(material, 1, duration, callback));
}
public IEnumerator FadeOut(Material material, float duration, Action callback = null)
{
yield return FadeTo(material, 0, duration, callback));
}
There are a lot of ways you could do this, but I personally in this case would create new coroutines FadeIn and FadeOut, instead of directly calling the following:
fadeCoroutine = StartCoroutine(FadeTo(objectsToFadeMaterials[i], 0, duration));
Then, at the end of your FadeOut coroutine you can take some additional step(s) to trigger a teleport or whatever else you need to trigger. It looks like you don't want your Fading to hold a reference to your Teleporting, which is smart, so you could choose to fire an event instead that your Teleporting component can subscribe to.

Can't make cooldown work, bugs out and isn't working properly

So I am making a VR game and what I want to do is, as soon as I press the trigger on the joystick the "sword" gets activated and can stay activated for 1 second, after that it has a cooldown of 1 second also in which it cannot get activated, and then it resets. I thought it would be simple but I can't for the life of me make it work.
Here's the code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
public class Sword : MonoBehaviour
{
public SteamVR_Action_Boolean ActivateSword;
public SteamVR_Input_Sources handType;
private bool IsSwordActivated = false;
private bool canSwordGetActivated = true;
private bool cooldownStart = false;
public Material activatedSword;
public Material defaultSword;
public float timeStamp;
public float timer = 0;
public float cooldown = 2;
void Start()
{
ActivateSword.AddOnStateDownListener(TriggerDown, handType);
ActivateSword.AddOnStateUpListener(TriggerUp, handType);
timeStamp = Time.time;
}
public void TriggerUp(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
{
Debug.Log("Trigger is up");
IsSwordActivated = false;
this.GetComponent<MeshRenderer>().material = defaultSword;
}
public void TriggerDown(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
{
if (canSwordGetActivated == true)
{
Debug.Log("Trigger is down");
IsSwordActivated = true;
cooldownStart = true;
this.GetComponent<MeshRenderer>().material = activatedSword;
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
if (IsSwordActivated == true)
{
Destroy(collision.gameObject);
}
}
}
private void Update()
{
//if (timeStamp <= Time.time)
//{
// if (IsSwordActivated == true)
// {
// timeStamp += 2;
// canSwordGetActivated = false;
// Debug.Log("test");
// }
//}
if (cooldownStart == true)
{
timer += Time.deltaTime;
cooldown -= Time.deltaTime;
if (timer >= 1f)
{
this.GetComponent<MeshRenderer>().material = defaultSword;
IsSwordActivated = false;
timer = 0;
}
if (timer == 0)
{
canSwordGetActivated = false;
}
if (cooldown <= 1f)
{
canSwordGetActivated = false;
}
if (cooldown <= 0)
{
cooldown = 2f;
canSwordGetActivated = true;
cooldownStart = false;
}
}
}
}
You should not use Update but a Coroutine for that. Especially the "cooldown" should run independently from the "timer".
// Not needed
//private bool cooldownStart = false;
//public float timer = 0;
// reference this already via the Inspector if possible
[SerializeField] private MeshRenderer _meshRenderer;
[SerializeField] private float cooldownTime = 1;
[SerializeField] private float maxEnabledTime = 1;
// Otherwise get it only ONCE on runtime
private void Awake()
{
if(!_meshRenderer) _meshRenderer = GetComponent<MeshRenderer>();
}
public void TriggerUp(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
{
Debug.Log("Trigger is up");
// stop the timeout
StopAllCoroutines();
// disable sword and start cooldown
StartCoroutine(SwordCooldown());
}
public void TriggerDown(SteamVR_Action_Boolean fromAction, SteamVR_Input_Sources fromSource)
{
if(IsSwordActivated) return;
if (!canSwordGetActivated) return;
Debug.Log("Trigger is down");
// start timeout
StartCoroutine(SwordEnabledTimer());
}
///<summary>
/// Disables sword and Runs cooldown before sword can be enabled again
///<summary>
private IEnumerator SwordCooldown()
{
canSwordGetActivated = false;
IsSwordActivated = false;
_meshRenderer.material = defaultSword;
yield return new WaitForSeconds(cooldownTime);
canSwordGetActivated = true;
}
///<summary>
/// Disables the sword and jumps to cooldown after it was enabled for too long
///<summary>
private IEnumerator SwordEnabledTimer()
{
canSwordGetActivated = false;
yield return new WaitForSeconds(maxEnabledTime);
StartCoroutine(SwordCooldown());
}
See WaitForSeconds
Sideeffect/Advantage:
Coroutines are often better read- and maintainable and more flexible then polling states in Update!
For example You can now very simple extend both routines and add a progress display for both like e.g.
private IEnumerator SwordCooldown()
{
canSwordGetActivated = false;
IsSwordActivated = false;
_meshRenderer.material = defaultSword;
var timePassed = 0f;
while(timePassed < cooldownTime)
{
var cooldownProgress = timePassed / cooldownTime;
// do something with the cooldownProgress value 0-1
timePassed += Mathf.Min(Time.deltaTime, cooldownTime - timePassed);
yield return null;
}
canSwordGetActivated = true;
}
One simple way of doing this would be a coroutine:
class Sword {
private bool isCoolingDown;
public void Swing() {
if (isCoolingDown) {
Debug.Log("Sorry, cooling down right now");
return;
}
StartCoroutine(DoSwingSword());
}
private IEnumerator DoSwingSword() {
isCoolingDown = true;
yield return new WaitForSeconds(1);
isCoolingDown = false;
}
}
This will use a bool to track if you are in cooled down state and automatically reset this bool after one second, without you having to track Time.deltaTime. You can then wrap the rest of your logic around this bool.

Unity3d New Input System(2.8), can't reference Input Action in the editor

I've just updated to the new Input System from 2.7 to 2.8.
How the new Input System works is you create an input actions asset by going to Create-> Input Actions
.
This creates an asset where actions can be mapped to keys. One then create a C# script from this asset and use it in their code. Which is what I did. I called the Asset MyInput.inputactions and the C# script is MyInput.cs
When you use the generated C# script this way you need to reference the asset in your script. However, after the update, it seems this is impossible to do from the editor. When I define a public MyInput variable in my class, like so:
public class ShapeMover: MonoBehaviour
{
public MyInput controls;
private float _lastFallTime;
private float _fallSpeed;
private ShapeSpawner _spawn;
private GameObject _shapeToMove;
private Transform _shapeToMoveTransform;
private bool _isGameOver;
private const float _leftRotationAngle = (float) -1.57079633;
private const float _rightRotationAngle = (float) 1.57079633;
}
It isn't exposed in the inspector:
And I get an obvious NullReferenceExceptionerror when I try to access the controls variable.
Am I doing something wrong?
How can I reference the asset from the inspector? I have tried adding [SerializeField] to the public declaration, it didn't help.
I was following this video and it worked fine until I updated to a newer Input System version.
For reference, this is the full ShapeMover class:
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace _Scripts
{
public class ShapeMover : MonoBehaviour
{
[SerializeField]
public MyInput controls;
private float _lastFallTime;
private float _fallSpeed;
private ShapeSpawner _spawn;
private GameObject _shapeToMove;
private Transform _shapeToMoveTransform;
private bool _isGameOver;
private const float _leftRotationAngle = (float) -1.57079633;
private const float _rightRotationAngle = (float) 1.57079633;
private void Awake()
{
_spawn = FindObjectOfType<ShapeSpawner>();
_lastFallTime = 0f;
_fallSpeed = GameGrid.Instance.GetFallSpeed();
_isGameOver = false;
Debug.Log("Registering controls callbacks...");
controls.Player.Movement.performed += ctx => Movement(ctx.ReadValue<Vector2>(), true);
controls.Player.Drop.performed += ctx => Drop();
controls.Menu.Reset.performed += ctx => Restart();
controls.Menu.Pause.performed += ctx => PauseToggle();
SetShapeToMove();
}
private void Restart()
{
GameGrid.Instance.ResetGame();
_isGameOver = false;
SetShapeToMove();
}
private void PauseToggle()
{
Debug.Log("Got Pause input");
var currentPauseState = GameGrid.Instance.IsPaused;
//If not paused, will pause
if (!currentPauseState)
{
// controls.Player.Movement.Disable();
// controls.Player.Drop.Disable();
// controls.Player.Menu.Disable();
// controls.Player.Disable();
GameGrid.Instance.IsPaused = true;
}
else
{
// controls.Player.Movement.Enable();
// controls.Player.Drop.Enable();
// controls.Player.Menu.Enable();
// controls.Player.Enable();
GameGrid.Instance.IsPaused = false;
}
}
private void Drop()
{
// Debug.Log("Should Drop Shape!");
bool didMove = true;
while (didMove)
{
didMove = Movement(new Vector2(0, -1), false);
}
}
private bool Movement(Vector2 direction, bool isFromInput)
{
if (isFromInput)
{
Debug.Log($"Got input {direction.ToString()}");
}
//Disable movement controls when game is over.
if (_isGameOver)
{
return false;
}
var oldPosition = _shapeToMoveTransform.position;
var oldRotation = _shapeToMoveTransform.rotation;
// Transform[] children = _shapeToMoveTransform.Cast<Transform>().ToArray();
var didMove = true;
var didEndMovement = false;
GameGrid.Instance.RemoveShapeFromGrid(_shapeToMoveTransform);
if (direction.x < 0)
{
didMove = MoveLeft();
}
else if (direction.x > 0)
{
didMove = MoveRight();
}
else if (direction.y > 0)
{
didMove = RotateLeft();
}
else if (direction.y < 0)
{
didMove = MoveDown();
if (!didMove)
{
didEndMovement = true;
}
}
//If Shape didn't move, restore previous position.
if (!didMove)
{
_shapeToMoveTransform.position = oldPosition;
_shapeToMoveTransform.rotation = oldRotation;
}
GameGrid.Instance.AddShapeToGrid(_shapeToMoveTransform);
// Debug.Log($"Shape {_shapeToMove.name} Position after movement Did Move: {didMove.ToString()}");
// Transform[] children = _shapeToMoveTransform.Cast<Transform>().ToArray();
// var lowestChild = children.OrderBy(x => x.position.y).First();
// Debug.Log($"{lowestChild.position.ToString()}");
if (didEndMovement)
{
GameGrid.Instance.ClearRows(_shapeToMoveTransform);
_isGameOver = GameGrid.Instance.IsGameOver(_shapeToMoveTransform);
if (!_isGameOver)
{
SetShapeToMove();
}
}
return didMove;
}
private void SetShapeToMove()
{
_shapeToMove = _spawn.SpawnShape();
_shapeToMoveTransform = _shapeToMove.transform;
}
private void Update()
{
if (_isGameOver)
{
return;
}
if (GameGrid.Instance.IsPaused)
{
return;
}
var time = Time.time;
if (!(time - (_lastFallTime + _fallSpeed) > 0))
{
return;
}
Movement(new Vector2(0, -1), false);
_lastFallTime = time;
_fallSpeed = GameGrid.Instance.GetFallSpeed();
}
private bool MoveLeft()
{
_shapeToMoveTransform.position += Vector3.right;
return GameGrid.Instance.CanMove(_shapeToMoveTransform);
}
private bool MoveRight()
{
_shapeToMoveTransform.position += Vector3.left;
return GameGrid.Instance.CanMove(_shapeToMoveTransform);
}
private bool MoveDown()
{
_shapeToMoveTransform.position += Vector3.down;
return GameGrid.Instance.CanMove(_shapeToMoveTransform);
}
private bool RotateLeft()
{
_shapeToMoveTransform.Rotate(0, 0, -90);
// foreach (Transform child in _shapeToMoveTransform)
// {
// RotateTransform(child, _leftRotationAngle);
// }
return GameGrid.Instance.CanMove(_shapeToMoveTransform);
}
private void RotateTransform(Transform transformToRotate, float rotationAngleRadian)
{
var currentLocalPosition = transformToRotate.localPosition;
var currentX = currentLocalPosition.x;
var currentY = currentLocalPosition.y;
var rotatedX = currentX * Mathf.Cos(rotationAngleRadian) - currentY * Mathf.Sin(rotationAngleRadian);
var rotatedY = currentX * Mathf.Sin(rotationAngleRadian) + currentY * Mathf.Cos(rotationAngleRadian);
transformToRotate.localPosition = new Vector2(rotatedX, rotatedY);
// Debug.Log($"Position after rotation is: {transformToRotate.localPosition.ToString()}");
}
private bool RotateRight()
{
_shapeToMoveTransform.Rotate(0, 0, -90);
return GameGrid.Instance.CanMove(_shapeToMoveTransform);
}
private void OnEnable()
{
Debug.Log("Controls Enabled...");
controls.Enable();
}
// private void OnDisable()
// {
// Debug.Log("Controls Disabled...");
// controls.Disable();
// }
}
}
Just as you said, you can't reference the new generated input class anymore.
To make it works, i instantiated the class, and use the SetCallbacks method, like this :
private MyInput _inputs;
public void Awake()
{
_inputs = new MyInput();
}
Truth be told, i don't know if it's the intended way of using the input class, but it works.
EDIT :
Starting from the 2.8 preview, an interface is automatically generated. I can only recommend it, cause it's very easy to use, you just need to inherits from IYourActionsSetNameActions and add the callbacks. (Also, you have to enable / disable the actions set, but you should be able to do it in another script)
Here is a complete base example, using your naming :
public class ShapeMover : MonoBehaviour, MyInput.IPlayerActions
{
private MyInput _inputs;
public void Awake()
{
_inputs = new MyInput();
_inputs.Player.SetCallbacks(this);
}
public void OnEnable()
{
_inputs.Player.Enable();
}
public void OnDisable()
{
_inputs.Player.Disable();
}
public void OnMovement(InputAction.CallbackContext context)
{
Vector2 delta = context.ReadValue<Vector2>();
transform.position += new Vector3(delta.x, 0, delta.y);
}
public void OnDrop(InputAction.CallbackContext context)
{
//TODO
}
// ...
}

UnityStandardAssets.ImageEffects cannot be read

I'm trying to make use of the Blur effect but I'm getting an error reading that the the type or namespace cannot be found. Thanks in advance.
I'm new to unity so I apologize if this is an easy fix. Here is a screenshot of my code.
using UnityEngine;
using System.Collections;
using UnityStandardAssets.Characters.FirstPerson;
using UnityStandardAssets.ImageEffects;
using System;
using System.Reflection;
using Assets.SwimmingSystem.Scripts;
namespace Assets.SwimmingSystem.Scripts
{
public class Swim : MonoBehaviour
{
private FirstPersonController _firstPersonController;
private CharacterController _characterController;
private Blur _blur;
private Color _fogColorWater;
// Default settings on start
private float _defWalkspeed, _defJumpspeed, _defRunspeed, _defGravityMultiplier;
private FogMode _defFogMode;
private float _defFogDensity;
private Color _defFogColor;
private bool _defFogEnabled;
private Camera _camera;
private bool _isInWater = false;
private float _waterSurfacePosY = 0.0f;
public float _aboveWaterTolerance = 0.5f;
[Range(0.5f, 3.0f)]
public float _upDownSpeed = 1.0f;
// Use this for initialization
void Start()
{
_firstPersonController = GetComponent<FirstPersonController>();
_characterController = GetComponent<CharacterController>();
_fogColorWater = new Color(0.2f, 0.65f, 0.75f, 0.5f);
Transform fpChar = transform.FindChild("FirstPersonCharacter");
_blur = fpChar.GetComponent<Blur>();
_camera = fpChar.GetComponent<Camera>();
// Default values for FirstPersonController on start
_defWalkspeed = WalkSpeed;
_defRunspeed = RunSpeed;
_defJumpspeed = JumpSpeed;
_defGravityMultiplier = GravityMultiplier;
_defFogMode = RenderSettings.fogMode;
_defFogDensity = RenderSettings.fogDensity;
_defFogColor = RenderSettings.fogColor;
_defFogEnabled = RenderSettings.fog;
}
// Update is called once per frame
void Update()
{
// Set underwater rendering or default
if (IsUnderwater())
{
SetRenderDiving();
}
else
{
SetRenderDefault();
}
// Handle swimming
// 1. If camera underwater we dive
if (_isInWater)
{
if (IsUnderwater())
{
DoDiving();
}
else
{
// we are grounded and not underwater, we might walk as well
if (_characterController.isGrounded)
{
DoWalking();
}
else
{
// we are not grounded so we are swimming above the surface
HandleUpDownSwimMovement();
}
}
}
else
{
DoWalking();
}
}
// Check if we are underwater
private bool IsUnderwater()
{
return _camera.gameObject.transform.position.y < (_waterSurfacePosY);
}
// Let's walk
private void DoWalking()
{
StickToGroundForce = 10;
WalkSpeed = Mathf.Lerp(WalkSpeed, _defWalkspeed, Time.deltaTime * 3.0f);
RunSpeed = Mathf.Lerp(RunSpeed, _defRunspeed, Time.deltaTime * 3.0f);
JumpSpeed = _defJumpspeed;
GravityMultiplier = _defGravityMultiplier;
UserHeadBob = true;
}
// Let's dive
private void DoDiving()
{
WalkSpeed = 1.0f;
RunSpeed = 2.0f;
JumpSpeed = 0.0f;
UserHeadBob = false;
HandleUpDownSwimMovement();
}
private void HandleUpDownSwimMovement()
{
StickToGroundForce = 0.0f;
GravityMultiplier = 0.1f;
Vector3 mv = MoveDir;
if (Input.GetKey(KeyCode.E))
{
// go upwards
if (_camera.gameObject.transform.position.y < _waterSurfacePosY + _aboveWaterTolerance)
{
mv.y = _upDownSpeed;
}
}
else if (Input.GetKey(KeyCode.Q))
{
// go down
mv.y = -_upDownSpeed;
}
MoveDir = mv;
}
// Rendering when diving
private void SetRenderDiving()
{
RenderSettings.fog = true;
RenderSettings.fogColor = _fogColorWater;
RenderSettings.fogDensity = 0.1f;
RenderSettings.fogMode = FogMode.Exponential;
_blur.enabled = true;
}
// Rendering when above water
private void SetRenderDefault()
{
RenderSettings.fogColor = _defFogColor;
RenderSettings.fogDensity = _defFogDensity;
RenderSettings.fog = _defFogEnabled;
RenderSettings.fogMode = _defFogMode;
_blur.enabled = false;
}
public void OnTriggerEnter(Collider other)
{
if (LayerMask.LayerToName(other.gameObject.layer) == "Water")
{
// We enter the water... doesn't matter if we return from unserwater, we are still in the water
_isInWater = true;
Debug.Log("Water Trigger Enter : " + _isInWater);
}
}
public void OnTriggerExit(Collider other)
{
if (LayerMask.LayerToName(other.gameObject.layer) == "Water" && _isInWater)
{
// we are leaving the water, or are we under the sureface?
_waterSurfacePosY = other.transform.position.y;
float fpsPosY = this.transform.position.y;
if (fpsPosY > _waterSurfacePosY)
{
// ok we really left the water
_isInWater = false;
}
Debug.Log("Water Trigger Exit : " + _isInWater);
}
}
#region Properties by reflection
private Vector3 MoveDir
{
get
{
return (Vector3)ReflectionUtil.GetFieldValue(_firstPersonController, "m_MoveDir");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_MoveDir", value);
}
}
public float WalkSpeed
{
get
{
return (float)ReflectionUtil.GetFieldValue(_firstPersonController, "m_WalkSpeed");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_WalkSpeed", value);
}
}
public float RunSpeed
{
get
{
return (float)ReflectionUtil.GetFieldValue(_firstPersonController, "m_RunSpeed");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_RunSpeed", value);
}
}
public float JumpSpeed
{
get
{
return (float)ReflectionUtil.GetFieldValue(_firstPersonController, "m_JumpSpeed");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_JumpSpeed", value);
}
}
public float GravityMultiplier
{
get
{
return (float)ReflectionUtil.GetFieldValue(_firstPersonController, "m_GravityMultiplier");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_GravityMultiplier", value);
}
}
public float StickToGroundForce
{
get
{
return (float)ReflectionUtil.GetFieldValue(_firstPersonController, "m_StickToGroundForce");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_StickToGroundForce", value);
}
}
public bool UserHeadBob
{
get
{
return (bool)ReflectionUtil.GetFieldValue(_firstPersonController, "m_UseHeadBob");
}
set
{
ReflectionUtil.SetFieldValue(_firstPersonController, "m_UseHeadBob", value);
}
}
#endregion
}
}
Make sure you are using the pro version of unity to make use of ImageEffects feature.
"The Blur image effect blurs the rendered image in real-time.
As with the other image effects, this effect is only available in Unity Pro and you must have the Pro Standard Assets installed before it becomes available."
Taken from : https://docs.unity3d.com/462/Documentation/Manual/script-BlurEffect.html

no overload for method 'Play' takes 0 arguments, more context

Im not really sure whats wrong, I'm pretty inexperienced with C#, and i posted this with everyone saying there isn't enough context, so Im posting the whole script. It isn't that long though, I just need this help!
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class MusicPlayer : MonoBehaviour {
public GUISkin skin;
public Song[] playlist;
public AudioClip mlgSong;
public AudioSource fastSource;
int currentSongID;
bool isPlaying;
[System.NonSerialized]
public bool fastMode = false;
string currentSongCredits;
//Song credits
float timer = 0;
float slidePosition;
float slidePositionMax = 20;
void Start() {
slidePosition = slidePositionMax;
ShuffleSongs();
audio.clip = playlist[0].clip;
currentSongID = 0;
isPlaying = audio.isPlaying;
if (!GameSettings.music) {
fastSource.Stop();
}
}
void Update() {
if ((!audio.isPlaying || GameSettings.keybinds.GetKeyDown("nextsong")) && isPlaying) {
if (currentSongID<playlist.Length-1) {
currentSongID++;
} else {
currentSongID = 0;
}
audio.clip = playlist[currentSongID].clip;
slidePosition = slidePositionMax;
Play (); //The error is here...
}
if ((!audio.isPlaying || GameSettings.keybinds.GetKeyDown("lastsong")) && isPlaying) {
if (currentSongID<playlist.Length+1) {
currentSongID++;
} else {
currentSongID = playlist.Length;
}
audio.clip = playlist[currentSongID].clip;
slidePosition = slidePositionMax;
Play (); //The error is also here.
}
//Timer
if (timer > 0) {
timer -= Time.deltaTime;
}
if (fastMode && fastSource.volume < 1) {
fastSource.volume = Mathf.Min(1,fastSource.volume + Time.deltaTime * 0.25f);
audio.volume = 0.5f - fastSource.volume/2;
}
if (!fastMode && fastSource.volume > 0) {
fastSource.volume = Mathf.Max(0,fastSource.volume - Time.deltaTime * 0.5f);
audio.volume = 0.5f - fastSource.volume/2;
}
if (timer > 0) {
slidePosition = Mathf.Lerp(slidePosition,0,Time.deltaTime);
} else {
slidePosition = Mathf.Lerp(slidePosition,slidePositionMax,Time.deltaTime);
}
}
public void Pause() {
Play (playlist[currentSongID].name);
}
public void Play(string credits) {
currentSongCredits = "Now playing: " + credits;
if (FindObjectOfType<MlgMode>() != null) {//IS MLG MODE
audio.clip = mlgSong;
currentSongCredits = "Now playing: xXxSW3GST3PxXx";
FindObjectOfType<MlgMode>().StartTheShit();//Start the wubs
}
isPlaying = true;
if (!audio.mute) {
timer = 8;
}
audio.Play();
}
void OnGUI() {
if (slidePosition < slidePositionMax-0.1f) {
GUI.skin = skin;
GUIStyle style = new GUIStyle(GUI.skin.label);
style.fontSize = 16;
style.alignment = TextAnchor.MiddleRight;
Rect rect = new Rect(0,Screen.height-30+slidePosition,Screen.width,30);
//GUIX.ShadowLabel(rect,currentSongCredits,style,1);
GUILayout.BeginArea(rect);
GUILayout.FlexibleSpace (); //Push down
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); //Push to the right
GUILayout.Label(currentSongCredits,GUI.skin.GetStyle("SoundCredits"),GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
}
void ShuffleSongs() {
//Shuffle playlist using Fisher-Yates algorithm
for (int i = playlist.Length;i > 1;i--) {
int j = Random.Range(0,i);
Song tmp = playlist[j];
playlist[j] = playlist[i - 1];
playlist[i - 1] = tmp;
}
}
}
[System.Serializable]
public class Song {
public string name;
public AudioClip clip;
}
Your Play method is declared like this:
public void Play(string credits)
but you are calling it like this:
Play();
You need to include a string as a parameter when you call it.
Play("White and Nerdy - Weird Al Yankovic");
Your Play(string credits) method is expecting a string called credits. Since you call Play() without putting a string there, it is giving you an error.
What it is looking for is an overloaded method, another form of Play() without the string and when it doesn't find that you receive that error.

Categories

Resources