I want to render this card and the first time it's loaded, the animation start once. What I want is the default there is no animation happen. Does anyone know how to make this happen?
class Card extends AnimationComponent {
Card(width, height)
: super.sequenced(width, height, 'card.png', 5,
textureWidth: 144.0, textureHeight: 220.0, loop: false);
}
class GameScreen extends BaseGame {
GameScreen({#required this.size}) {
add(Card(0,0));
}
}
According to the source code, you'll able to use Animation to control the frame.
For simple, just don't call update and keep rendering, the frame index will not be updated.
void update(double dt) {
clock += dt;
elapsed += dt;
if (isSingleFrame) {
return;
}
if (!loop && isLastFrame) {
onCompleteAnimation?.call();
return;
}
while (clock > currentFrame.stepTime) {
if (!isLastFrame) {
clock -= currentFrame.stepTime;
currentIndex++;
} else if (loop) {
clock -= currentFrame.stepTime;
currentIndex = 0;
} else {
break;
}
}
}
So you could just override the update method to get the controll of sprite animations.
Related
I would like a Unity progress slider to fill up when I press the spacebar. Currently, I have to mash the spacebar 100 times to fill up the progress bar.
It fills the progress slider automatically when moved to update().
It fills the progress slider when I hold the spacebar if I change Input.GetKeyDown to Input.GetKey.
But I don't want to hold the spacebar down. I want to press it once to start have the slider value gradually fill up the progress bar.
void Start()
{
sliderValue = 1.0f;
}
void Update()
{
pressSpacebar();
}
void pressSpacebar()
{
if (Input.GetKeyDown("space"))
{
filluptheslider();
}
}
void filluptheslider()
{
ProgressSlider.value += sliderValue * Time.deltaTime;
}
There are a few ways to handle this:
Method 1
Boolean value in the class to track the pressed state:
bool pressed = false;
void pressSpacebar()
{
if (Input.GetKeyDown("space"))
{
filluptheslider();
}
if(pressed)
{
filluptheslider();
}
}
Method 2
Coroutine that starts after space is pressed.
void pressSpacebar()
{
if (Input.GetKeyDown("space"))
{
StartCoroutine(FillUpTheSlider);
}
}
IEnumerator FillUpTheSlider()
{
while(ProgressSlider.value < ProgressSlider.maxValue)
{
ProgressSlider.value += sliderValue * Time.deltaTime;
yield return null;
}
}
If you press the space bar multiple times, multiple coroutines will spawn and it will fill faster. You can optionally add the following before you start the coroutine to prevent this behaviour:
StopCoroutine(FillUpTheSlider)
You could alternatively combine method 1 and 2 to remove this behaviour.
bool isFull = false;
bool isPressed = false;
void Update
{
If (Input.GetKeyDown(KeyCode.Space)
&&
!isFull)
{
isPressed = true;
}
if(isPressed)
{
//if you want fill to increase every 0.05 seconds.
StartCoroutine(FillGradually(0.05f));
isPressed = false;
}
}
Ienumerator FillGradually(float fillOffset)
{
//If 100 is your max value
while(ProgressSlider.value < 100)
{
ProgressSlider.value += 1 * Time.deltaTime;
yield return new WaitForSeconds(fillOffset);
}
isFull = true;
}
You can just use a bool condition and when space is pressed, you can just make it true once and when it is true, it will automatically start filling.
bool isSpacePressed; //bydefault, bool class variable is set to false //when initialized
update()
{
if(isSpacePressed==true) //no need to mention ==true just added to make it //readable
{
image.fillAmount=fillvalue+0.1f;
}
}
if(input.GetKey(keyCode.Space)==true)
{
isSpacePressed=true;
}
I want to trigger an event after tot seconds of long press on a touch screen.
I'm trying to achieve this goal with the following code.
The problem is that the time that has passed is, in some way, random.
private float timePressed = 0.0f;
private float timeLastPress = 0.0f;
public float timeDelayThreshold = 2.0f;
void Update() {
checkForLongPress(timeDelayThreshold);
}
void checkForLongPress(float tim) {
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
// If the user puts her finger on screen...
Debug.Log("Touch start");
timePressed = Time.time - timeLastPress;
}
if (Input.GetTouch(0).phase == TouchPhase.Ended)
{
// If the user raises her finger from screen
timeLastPress = Time.time;
Debug.Log("Releasing Touch");
Debug.Log("Time passed --> " + timePressed);
if (timePressed > tim)
{
Debug.Log("Closing APP");
// Is the time pressed greater than our time delay threshold?
Application.Quit();
}
}
}
}
The Fact is that this condition "(timePressed > tim)" is never true and i do not understand why.
Time.time returns The time at the beginning of this frame (Read Only). This is the time in seconds since the start of the game..
Fixed pseudo code:
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
_timePressed = Time.time;
return;
}
if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
var deltaTime = Time.time - _timePressed;
if (deltaTime > _maxTimeTreshold)
{
Application.Quit();
}
}
Can I somehow find out is it the first frame the user click on rotater, last frame or middle?
Handles.RotationHandle(...)
or
Handles.PositionHandle(...)
I need to know when the user start rotating/moving and when stop it.
Then you just need to add a variable to save the state. Something like this:
bool rotating;
void Update () {
if (rotating != Handles.RotationHandle(..)) {
rotating = !rotating;
if (rotating) {
//start rotation
} else {
//just stopped
}
} else if (rotating) {
//in rotating
}
}
I have a VR Scene with a C# Script on the camera that allows the user to Click Once to move and again to stop.
public float speed = 1.0f;
public bool startedMoving = true;
public GameObject myCam;
// Update is called once per frame
void Update () {
if (startedMoving) {
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
// if(Input.GetButtonDown("Fire1")){
if (Input.GetMouseButton(0)){
startedMoving = !startedMoving;
}
}
What I want to know is how I can CLICK & HOLD to move Backwards..?
Thank you!
~ b
Use enum the represent the status of the mouse instead of startedMoving or multiple booleans that will make everything easier to implement. The comment in the code describes how it works.
using UnityEngine;
using System.Collections;
public class ClickAndHeld : MonoBehaviour
{
public GameObject myCam;
CLICK_MODE clickMode = CLICK_MODE.NO_CLICK;
MOVE_DIRECTION moveDir = MOVE_DIRECTION.IDLE;
public float speed = 1.0f;
//If down for 0.5 secods the it is considered Click and Hold instead of Click
float clickHoldDetectTime = 0.5f;
float clickCounter = 0; //Dont not change
void Start()
{
StartCoroutine(mover());
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
//If in NO_CLICK, set to CLICKED
if (clickMode == CLICK_MODE.NO_CLICK)
{
//Change the mode to CLICKED
clickMode = CLICK_MODE.CLICKED;
}
//If in CLICKED mode, start counting to clickHoldDetectTime
if (clickMode == CLICK_MODE.CLICKED)
{
clickCounter += Time.deltaTime; //Increment counter
//Check if we have reached the clickHoldDetectTime time
if (clickCounter > clickHoldDetectTime)
{
//Reset Counter
clickCounter = 0;
//Change the mode to CLICK_AND_HELD
clickMode = CLICK_MODE.CLICK_AND_HELD;
}
}
//If STILL down and the the current mode is CLICK_AND_HELD then do clickedAndHeldDown stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
clickedAndHeldDown();
}
}
else
{
//If released and the current mode is CLICKED then do clicked stuff
if (clickMode == CLICK_MODE.CLICKED)
{
clicked();
}
//If released and the current mode is CLICK_AND_HELD, change to RELEASED then do relased stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
//Change the mode to RELEASED
clickMode = CLICK_MODE.RELEASED;
mouseReleasedAfterBeingHeld();
}
//Reset each time mouse button is released
reset();
}
}
IEnumerator mover()
{
while (true)
{
if (moveDir == MOVE_DIRECTION.IDLE)
{
}
//Move Forward
if (moveDir == MOVE_DIRECTION.FORWARD)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
//Move Backward
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
yield return null;
}
}
private void clicked()
{
Debug.Log("CLICKED");
//If Idle, become Forward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.FORWARD;
}
//If forward, moves become idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If backward, moves become idle
else if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
private void clickedAndHeldDown()
{
Debug.Log("CLICKED AND HELD");
//If Idle, becomes backward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.BACKWARD;
}
}
//Called when released after being RELEASED from CLICKED_HELD
private void mouseReleasedAfterBeingHeld()
{
Debug.Log("RELEASED AFTER CLICKED AND HELD");
//If backward, move becomes idle
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If forward, move becomes idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
void reset()
{
clickMode = CLICK_MODE.NO_CLICK;
clickCounter = 0;
}
}
public enum CLICK_MODE
{
NO_CLICK, CLICKED, CLICK_AND_HELD, RELEASED
}
public enum MOVE_DIRECTION
{
IDLE, FORWARD, BACKWARD
}
Because you only have one trigger action you're going to have to implement something time based for toggling forward/backwards movement. For example, if you press and release the trigger quickly then forward walk could be toggled, but if you're holding the trigger after N length of time then walk backwards.
He's a practical example to get you starting.
Pressing and releasing the trigger within 300ms will toggle forward movement
Pressing and holding the trigger for longer than 300ms will begin backwards movement, releasing the trigger then will stop backwards movement
This is a theoretical example
public float speed = 1.0f;
bool triggerPressed = false;
float triggerHeldTime = 0f;
public bool movingForwards = false;
public bool movingBackwards = false;
void Update ()
{
// increment hold time if we're still holding trigger
if (Input.GetMouseButton(0) && triggerPressed)
triggerHeldTime += Time.deltaTime;
if (Input.GetMouseButton(0) && !triggerPressed)
{
// reset everything when trigger initially pressed
movingForards = false;
movingBackwards = false;
triggerHeldTime = 0f;
triggerPressed = true;
}
else if (!Input.GetMouseButton(0) && triggerPressed)
{
// upon trigger release
triggerPressed = false;
// if we are not moving backwards, toggle forwards movement
if(!movingBackwards)
movingForwards = !movingForwards;
// always reset backwards movement when we release the trigger
movingBackwards = false;
triggerHeldTime = 0f;
}
// if the trigger has been held for 300ms then move backwards
if(triggerHeldTime > 0.3f)
{
moveForwards = false;
moveBackwards = true;
}
// actually perform the movement
if (moveForwards)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
else if(moveBackwards)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
}
I'm making my own game in Unity 4.6. I have background music playing all the time. But i want to give my players the possibility to mute the music with a simple toggle.
I'm using C#. Anyone any ideas on how to do this?
Would be a great help!
this is how i solved it!
using UnityEngine;
using System.Collections;
public class Mute: MonoBehaviour{
bool isMute;
public void MusicMute (){
if(isMute == true){
Debug.Log("Music On");
AudioListener.volume = 1;
isMute = false;
}
else {
Debug.Log("Music Off");
isMute = true;
AudioListener.volume = 0;
}
}
}
Imagining that you are using a GUI Button to toggle...
You can toggle the volume by following:
void OnGUI ()
{
if (GUI.Button (new Rect (0, 0, 30, 30), "Music")) {
if (audio.volume != 0) {
audio.volume = 0;
} else {
audio.volume = 1; //or whatever value you want
}
}
}
Otherwise you can play or stop by following:
void OnGUI ()
{
if (GUI.Button (new Rect (0, 0, 30, 30), "Music")) {
if (audio.isPlaying) {
audio.Stop ();
} else {
audio.Play ();
}
}
}
Hope it helps.