Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm getting some issues with logic and the behavior that is happening in my game.
I want to implement a powerup and this powerup just stops that character for certain of time. So to do it I'm simply disabling his script so he does nothing. Now this is working but the problem is I can't find a way to enable the script back to him after 5 seconds. I want to stop the character for 2 seconds.
Your code is wrong. You should be using Invoke.
It is extremely simple.
Something like ...
void ApplyPenalty()
{
yourPauseSystem = true;
Debug.Log("starting penalty..");
Invoke("EndPenalty", 5f);
}
void EndPenalty()
{
yourPauseSystem = false;
Debug.Log(" ...ended penalty");
}
Don't forget the Debug.Log statements.
Note that ideally ApplyPenalty (and EndPenalty) should be
ACTUALLY ON THOSE GAME OBJECTS.
actually put that code ON THOSE game objects, NOT here in the "collision object code". You get it?
So in your case, to apply the penalty, it will be something like ..
void OnCollisionEnter(Collision c)
{
if ( (c.gameObject.tag == "Character") )
c.GetComponent<YourHerosCode?().ApplyPenalty()
}
you see?
You MUST use the physics layers system. You literally have to use it to make collisions in Unity. you MUST use the "physics grid"...
to indicate what can collide with what. In your comment you say they "won't collide" but you can absolutely make anything collide (or not collide) with anything.
Note that in practice EVERYTHING needs its own physics layer, in Unity.
Certainly your hero, enemy etc will all have their own layer.
Tip: certainly "enemy projectiles" and "player projectiles" need their own separate layer, both.
If NullReference is on this line gameObject.GetComponent<PlayerControls>().enabled = true; is probably because you try to reference to a disable component.
Try to assign a var in Start() to the component
var playerController = gameObject.GetComponent<PlayerControls>();
and then use this to refer to it and enable/disable it:
playerController.enable = true; //or false
Related
i'm making my first enemy AI in unity. I'm trying to make a finished state machine with the animator controller to do it.
I just discovered the StateMachineBehaviour script which is called when the AI is in a state. It has multiple methods, including the OnStateEnter. It is called everytime the AI enter the state.
My problem is only about optimization, my AI need to get the GameObject "Player" in order to attack it. So i'm getting it in my OnStateEnter method for the moment, which i feel is bad, because i'm getting it every time the animation is called, i would like to get it only once, at the start.
I basicly need a start function but it's not working, i have made research and found nothing. I tried to watch video about people making a finished state machine but they are just getting the same GameObject multiple time ( example here : https://youtu.be/dYi-i83sq5g?t=409 ).
So, is there a way to have a start function or to get an element only once ?
I could make a bool that is called only the first time and that get the GameObject, but again that would be an "useless" if running in my function.
Any suggestions ? Thanks
No, unlike a MonoBehaviour a StateMachineBehaviour has no Start message only OnStateEnter, OnStateExit, OnStateIK, OnStateMove and OnStateUpdate.
There are also Awake and OnEnable but I'm pretty sure they are not used in the StateMachine and might not behave as expected.
You can however either use
OnStateMachineEnter
Called on the first Update frame when making a transition to a StateMachine. This is not called when making a transition into a StateMachine sub-state.
Or use a simple bool flag like
bool alreadyExecuted = false;
OnStateEnter()
{
if(alreadyExecuted) return;
// Do your stuff
alreadyExecuted = true;
}
(Just a guess)
In the Inspector you actually can enable and disable StateMachineBehaviours like components. So it might be able to do this also in script maybe the same way using
enabled = false;
but I didn't find anything about it in the API and since I'm currently on my Smartphone I can't test it.
Original question on the Unityforums here
I've been trying to get an animation to not only slow down and speed up, but also play backwards depending on user input for my Hololens-application. I am using the Mecanim system, not legacy animations.
The whole thing is supposed to happen at runtime, through dynamic user input.
I know that it's possible through scripting, as I had it working before I lost local progress and some files during some Unity-Collaborate issues. As stupid as it sounds, since then I have not been able to remember what I did different from my current approach.
Right now I'm manipulating the value Animator.speed, but that only works for values >= 0.
Any help would be greatly appreciated!
Edit: In case the link is not working or visible for anybody, here is my code:
private Animator anim;
//...
anim = gameObject.GetComponent<Animator>();
//...
public void OnManipulationUpdated(ManipulationEventData eventData)
{
if (anim.isActiveAndEnabled)
{
anim.speed = eventData.CumulativeDelta.x;
anim.Play("KA_Cover_Anim");
return;
}
//...
}
Edit2: Incorrectly marked as dupicate! The linked question does not regard a similar problem and required a different solution
Edit3: For clarification, the linked "duplicate" uses the legacy animation system which is irrelevant for my question. In Mecanim, the new animation system in Unity 5.xx, you can not access the Animations directly as shown in the selected answer. Neither is it possible to alter the animation speed as shown in in the second answer.
I'm not exactly sure what you're end goal is, but you can play animations backwards and at different speeds by using a parameter.
On the animation state, you can make it watch a parameter and multiply it against the default speed of the animation. All you need to do in code is something like
animator.setFloat("Speed",-1.0f);
Hope that helps.
I am fairly new to code, I know some of the basics but my knowledge is limited, so please let me know WHY in your answer if it's not too hard to explain, I'd like to learn rather than just be given the answer!
This code is the basic controls for a game i am making. I'll be explaining the premise of the game just so you're able to better grasp what my intent is.
The game will focus on the completion of mazes, however movement is restricted to only being able to go forward, and right. You may never do a u-turn, go left or go backwards.
With my current code, it is possible (VERY EASILY POSSIBLE) to just translate over the entire maze and the colliders for walls don't apply due to it being a translate, which to my understanding is essentially 'teleporting' it.
I've looked around on similar topics and discussions but I was unable to find any answers that addressed this kind of issue with colliders.
When the object collides with a 'wall' in my maze, I want the object to be reset to it's original position, or at the very least die, I'm not sure if that will affect the answer given, but just incase keep that in mind, thank you!
using UnityEngine;
using System.Collections;
public class Movement_Script : MonoBehaviour {
public float playerspeed = 1;
void Update () {
if(Input.GetKeyDown("up"))
{
transform.Translate(Vector3.up * 1);
}
if(Input.GetKeyDown("right"))
{
transform.Translate(Vector3.right * 1);
transform.Rotate(Time.deltaTime,0 ,-90);
}
}
}
When you control the transform, you are telling "Place this there".
So when you do:
transform.Translate(Vector3.up * 1); // multiplying by one is useless
you tell to displace the object by 0,1,0 from its current position. This is regardless of any environment. You still can detect collision by it won't be resolve by the engine, you would have to do it yourself.
Unity came up with a ready to use solution with the character controller component. It does the same as you do in your code but also perform a bunch of collision checks and resolve them. The latest version is actually using rigidbody for a more physical approach.
http://docs.unity3d.com/Manual/class-CharacterController.html
http://docs.unity3d.com/ScriptReference/CharacterController.Move.html
the Move method is the one to use for Unity to handle the whole process for you. I would recommend to install a basic four wall room with a few boxes here and there so that you get the grip of it. Then it will be easy to move on to do whatever you want with it, whether 2D or 3D movement.
I am working on Unity for a month. I am new on Unity and C#, before Unity I worked other game engines. Whatever I am working on infinite run game, I wrote random road generator. Road generator is working well but I have problem about updating road. I can update road manualy like this. How can I update it automaticly?
void Update()
{
if(Input.GetKeyDown(KeyCode.A)) UpdateRoad();
}
My UpdateRoad method adding road like this(I am using object pooling).
I want to update after Link Road, OnExitTrigger or something I dont know. How can I do it?
You would need to implement Object Pooling.
I would suggest making your Design of Objects first so you can test. Or if not use, the stock Blocks Primitive of Unity3D as your Prefabs. I hope you already know prefabs. It is a major key for making infinite runner. Actually a main core for making any kinds of game.
Prefabs is an Object File where you can Instantiate it in a location. So lets say you will generate a Flat walkable, then Generate a Pit. You would probably want to stack them together.
Now Generating them is easy. You would not like to go in an Update? Approach because most likely you're not going to update, but you're going to further stack what is going on ahead, based on your game logic.
To further Understand this, Unity3D already made a project or Fully Detailed tutorial. It maybe made in 2D but it is going to be the same, if you're going to change the Collider2D to Collider <- this is important in your case.
https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/infinite-runner
Update
You would need to create an Object, that is invisible. Meaning a Trigger.
Then on Trigger call your method UpdateRoad();
https://unity3d.com/learn/tutorials/modules/beginner/physics/colliders-as-triggers
Detailed Videos about Trigger.
If I understood your needs correctly, you could create Empty Object name it SpawnPoint, set position for Spawn Point as you need (out of the camera view) and then Instanciate random prefabs of road. Concerning On TriggerExit - it could be used to destroy "old piece of road". But to have it working properly, dont forget to set collider and rigitbody to your objects. Dont add collider2D or Rigitbody2d, add and use Box Collider and Rigitbody components
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am programming the table top game "Get Bit!". First i created a console version and now I'm trying to port it to Unity.
My Problem:
In console the whole game is linear. So PlayCards() asks the Player what card he wants to play and then waits until user enters its value.
In unity I'm trying to get the input via Buttons, but that does not wait for user Input and contues with MoveSwimmer() and so on. I tried to get the value via while(inupt == -1), but that freezes the whole game.
Currently the Run() method is in a class Game : MonoBehaviour attached to camera.
Here's the code of the problematic functions after taking McAden's advice:
void Game::Update ()
{
this.GameRun = true;
Debug.Log(string.Format("Round: {0}", (round - 1)));
Debug.Log("POSITION: " + PlayerPositionString());
while (GameRun)
{
PlayCards();
MoveSwimmers();
GetBit();
EndTurn();
}
Debug.Log(string.Format("Congrats! Player {0} won!", playerPosition.First()));
}
private void Game::PlayCards()
{
for (int i = 0; i < playerScripts.Count; i++)
{
if (playerScripts [i].IsAlive())
cardsPlayed.Add(playerScripts [i].PlaceCard());
}
}
override public Card Player::PlaceCard()
{
// a MonoBehaviour that shows for each card a Button that sets the value member ChoosenCardValue (on default -1).
GUICardChooser chooser = Camera.main.GetComponent<GUICardChooser>();
while (chooser.ChoosenCardValue == -1)
;
int cardIndex = cards.FindIndex(c => c.Value == chooser.ChoosenCardValue);
Card theChoosenOne = cards [cardIndex];
cards.RemoveAt(cardIndex);
return theChoosenOne;
}
Am I focussing on the wrong pattern? How can I fix this issue?
Thanks for help.
In Unity3D you don't need to define your own game loop. Unity already does that for you. Create an Update function.
Inside your Update function - check for input and react to it. Since it's in a loop, use if instead of while. Update is already within a loop though you might end up looking up the differences between it and FixedUpdate.
something like:
void Update
{
if (Input.GetKeyUp (KeyCode.LeftArrow))
{
DoSomething();
}
}
You'll want to research the different ways of dealing with input. You won't always want to use GetKeyUp. You might use GetAxis or GetButtonUp for example.
As #Didier suggests in his answer you'll probably want to end up implementing a State Machine of some sort in the long run.
First I think you should look through Unity docs and Unity samples.
But if you want to implement it one of the possibilities would be to create a state mashine. And inside your Update() method you will behave according to your current state. But it's just one possibility. It all depends on your gameplay...