I'm using a switch as a state manager for my XNA game. The switch is a part of main update method, so it's run every frame. Sometimes I need to set a timer value and it should only be set once per method call. There are multiple methods that set the timer per case, so it can't use the current and previous state numbers to check if it's ok to overwrite previous time.
case "state 34": {
SetTime(theTime); // should run only once
// other things
if (TheTimeisRight(time)) // runs every call
{
SetTime(theTime); // should run only once
if (TheTimeisRight(time))
{ /* some methods */ }
}
break; }
How can I make this work, or is there a better way to do this without going outside the switch? (changing SetTime method is ok, but I wouldn't like to clutter up the switch with additional code)
Another method: Introduce a wrapper around the method you want to call:
public sealed class RunOnceAction
{
private readonly Action F;
private bool hasRun;
public RunOnceAction(Action f)
{
F = f;
}
public void run()
{
if (hasRun) return;
F();
hasRun = true;
}
}
Then create var setTimeOnce = new RunOnceAction(() => SetTime(theTime)); before the switch statement, and call there as setTimeOnce.run(). Adjust for parameters/return values as necessary.
If you don't want to mess with boolean variables ala hasSetTimeAlready, you can always introduce another state that calls the method, then proceeds to the original state.
Put the call outside the loop.
You might need a separate conditional statement to determine whether it should run at all, but that's got to be infinitely better than trying to use flags and/or various other smelly-code approaches to control repetitions of the call.
Edit:
here is what I mean by putting it in one place outside of the switch:
if (someCondition && someOtherCondition && yetAnotherCondition)
setTime(theTime); // just one call, in one place, gets executed once
switch(someValue)
{
case "state 34": {
//SetTime(theTime); // no longer necessary
// other things
if (TheTimeisRight(time)) // runs every call
{
//SetTime(theTime); // no longer necessary
if (TheTimeisRight(time))
{ /* some methods */ }
}
break;
...etc...
}
A word of advice: use an enumeration for your switch value rather than a string.
To be brutally honest, this is about as much as anyone can realistically help you with this without seeing a more complete code sample (I think the sample you gave us is somewhat contrived and not quite accurate to what you have?). Chances are that the best way to get round this problem is to deconstruct the switch statement and start again because either maintaining a state machine is not the best way to handle this situation or you need to introduce some other states.
I have resorted to using HashSet<int> to check if the current SetTime(time, num) method has not been called before with if (!hashSet.Contains(num)).
void SetTime(int time, int num)
{
if (!hashSet.Contains(num))
{
theTime = time;
hashSet.Add(num);
}
}
Sure doesn't look too cool, but works and it doesn't damage method call too much (visually), so the switch's readability is saved.
Related
I've implemented a simple Behavior Tree algorithm which I intend to use inside a Unity project. It's mostly working as I expected, except I'm having trouble making proper use of it, which might be caused by some misunderstanding of mine. My problem is as follows:
If a leaf node takes a long time to finish, for instance, an action that makes a game unit follow a specific path, that means the leaf node is currently at the "running" state. However, if I return the state, I can no longer run the rest of the function, which means I can't reach my destination.
So my question is: what is the proper way to tell my tree that a leaf node is running?
Here's what I got on my ActionNode class:
public class ActionNode : BTNode
{
public delegate NodeStates ActionNodeDelegate();
protected ActionNodeDelegate nodeAction;
public ActionNode(ActionNodeDelegate action)
{
nodeAction = action;
}
public override NodeStates Evaluate()
{
switch (nodeAction())
{
case NodeStates.FAILURE:
currentNodeState = NodeStates.FAILURE;
return currentNodeState;
case NodeStates.SUCESS:
currentNodeState = NodeStates.SUCESS;
return currentNodeState;
case NodeStates.RUNNING:
currentNodeState = NodeStates.RUNNING;
return currentNodeState;
default:
currentNodeState = NodeStates.FAILURE;
return currentNodeState;
}
}
}
If you need to check the other classes, it's all based on this article. Linking it for the sake of keeping the thread cleaner.
As for an action example, consider this:
private NodeStates FollowPath() {
bool targetReached;
if (targetReachable)
targetReached = WalkToTarget();
if (targetReached)
return NodeStates.SUCESS;
else
return NodeStates.FAILURE;
}
What I'm wondering is, if WalkToTarget takes a long time, how do I return a "running" state?
I've read many different articles on the subject, but I can't seem to grasp the exact concept behind these states. I understand how I can, for instance, tell that a Sequence or Selector node is running.
The only idea that crossed my mind is that I'd store the remaining path inside a variable at my enemy class and call the method every game update tick, but I feel like that's just poor coding.
Are leaf nodes supposed to return "running" at any given moment? If so, in which cases would that happen? Any examples would be appreciated!
Okay, I figured out what I was doing wrong. I was assuming that my tree was responsible for executing the action code, when it is actually supposed to only evaluate the state of every node. In this case, my above example would change to something like this:
private NodeStates ShouldFollowPath() {
if (targetReachable && this.position != target.position)
return NodeStates.RUNNING;
else if (this.position == target.position)
return NodeStates.SUCESS;
else
return NodeStates.FAILURE;
}
And then I'd check the state of the above Node after evaluating the tree and execute my FollowPath code:
private ActionNode FollowPathNode = new ActioNode(ShouldFollowPath);
private void Update()
{
FollowPathNode.evaluate();
if (FollowPathNode.nodeState == NodeStates.RUNNING)
FollowPath();
}
In summary, I misunderstood the usage of the behavior tree. The above example solves my problems.
i have the following 3 examples which does the same thing
//case1 do it if the condition is valid
private void SetMultiplePropertyValues()
{
if (Keyboard.GetKeyStates(Key.CapsLock) == KeyStates.Toggled)
{
//do somthing
}
}
//case 2 return if the condition is not valid
private void SetMultiplePropertyValues()
{
if (Keyboard.GetKeyStates(Key.CapsLock) != KeyStates.Toggled) return;
//do somthing
}
//case 3 checking the condition in the calling scope
if (Keyboard.GetKeyStates(Key.CapsLock)== KeyStates.Toggled)
SetMultiplePropertyValues())
private void SetMultiplePropertyValues()
{
//do somthing
}
which one would you go with and why
They do not do the same thing because in the first two cases the name of the method is a lie; the method name should be SetValuesIfTheKeyStateIsToggled or TryToSetValues or some such thing. Don't say you're going to do a thing and then not do it. More generally: separate your concerns. I would choose a fourth option:
public void TryToFrob()
{
if (CanFrob()) DoFrob();
}
private bool CanFrob()
{
return Keyboard.GetKeyStates(Key.CapsLock) == KeyStates.Toggled;
}
private void DoFrob()
{
// frob!
}
Notice what is public and what is private.
This is a silly looking example because each one is so simple, but one can easily imagine a situation in which these methods are complex. Keep your policies and your mechanisms logically separated. The mechanism is "is the keyboard in a particular state?" The policy is "I have some conditions under which I can frob; we must never frob unless those conditions are met".
First of all, as we can see at code comments, they don't do the same thing. So I think that you're talking about code architecture rather than functionality.
Second, here in SO isn't about giving opinions, but I'll try say to you concrete things about these differences.
1- Common if approach
if (true == false)
{
return true;
}
vs.
2 - Single line if approach
if (true == false) return true;
Most of code convetions says to use the option 1, because they're easier to read and understant code, and avoid some mistakes. We need to also understand that convetions are not rules! so they're just convetions, but really try to avoid option 2 in most of the cases.
One more thing, some code convetions also says that's ok using option 2 when you need something very simple, like this given example which is really easy to read and understand. But take this like an exception from the 'rules'.
I tried this:
if(PauseButton.Image != global::GripAIConsole.Icons.Resume)
{
PauseButton.Image = global::GripAIConsole.Icons.Resume;
ToolTipMainWin.SetToolTip(PauseButton, "Resume / Step <F4>");
}
And it doesn't work. I would have thought it was comparing pointers internally to see if they were pointing at the same place.
You are working with resources, so if you want to make sure the reference is right, compare using the static method Object.ReferenceEquals(). As ChrisF said, you should not use this to determine application logic. Using a simple bool variable is much better (and slightly more performance friendly).
I would define the possible states with an enum:
public enum State {
Stopped,
Pausing,
Running
}
And then define a state property or variable:
State _state;
then Change the states as follows:
void ChangeState(State newState)
{
_state = newState;
switch (newState) {
case State.Stopped:
PauseButton.Image = global::GripAIConsole.Icons.Pause;
ToolTipMainWin.SetToolTip(PauseButton, "Start game <F5>");
break;
case State.Pausing:
PauseButton.Image = global::GripAIConsole.Icons.Resume;
ToolTipMainWin.SetToolTip(PauseButton, "Resume / Step <F4>");
break;
case State.Running:
PauseButton.Image = global::GripAIConsole.Icons.Pause;
ToolTipMainWin.SetToolTip(PauseButton, "Pause <F4> / Stop game <F6>");
break;
}
}
... or whatever your logic requires.
This is much cleaner and understandable. A picture has to do with the GUI, not with the logic. Inferring the state of the logic from things displayed on the forms is weird.
1) I'm working on a project and I saw this piece of code, I don't understand what is the point of the Monitor.Lock statement. Can someone explain what its trying to do?
2) the postscript underscroll in the parameter name is really annoying, anyone else seen this naming convention?
public class FieldsChangeableHelper<T> : IFieldsChangeable<T>
{
object _lock;
int _lockCount;
FieldChanges<T> _changes;
public FieldsChangeableHelper()
{
_lock = new object();
_lockCount = 0;
}
public void AddChange(T field_, object oldValue_)
{
if (_changes == null)
_changes = new FieldChanges<T>(field_, oldValue_);
else
_changes.AddChange(field_, oldValue_);
if (RaiseEvent(_changes))
_changes = null;
}
#region IFieldsChangeable Members
public void BeginUpdate()
{
if (System.Threading.Interlocked.Increment(ref _lockCount) == 1)
Monitor.Enter(_lock);
}
public void EndUpdate()
{
if (System.Threading.Interlocked.Decrement(ref _lockCount) == 0)
{
FieldChanges<T> changes = _changes;
_changes = null;
Monitor.Exit(_lock);
RaiseEvent(changes);
}
}
protected bool RaiseEvent(FieldChanges<T> changes_)
{
if (_lockCount == 0 && Changed != null && changes_ != null)
{
Changed(this, changes_);
return true;
}
return false;
}
public event FieldsChanged<T> Changed;
#endregion
}
Monitor.Lock locks the portion of code when multiple thread tries to execute the same piece in parallel. It is made to ensure that only 1 guy is altering/executing the context. Look at the MSDN.
Although its best practice that the locking object is always static, but in your case it is not. Which might pose some problem if your instantiating multiple objects on an open type.
Note one thing, in generics static on open T is different for different type, i.e static member in an Open Type class in your case is different for T i.e DateTime, string, etc.
In csharp, private members of a type are usually named with prefixed _
The way i read it: BeginUpdate() ensures that the current thread calling has exclusive access to the instance and that change events practically will be batched and raised once EndUpdate is called. The author wanted to deal with recursion by itself (e.g. calling BeginUpdate() on the same thread multiple times) and a mechanism to batch UpdateEvents untill after the lock has been released. Because, there is a potential deadlock when raising Events when you still have a lock on yourself. event subscribers might want to access your members and therefore have to lock the sender instance which is already locked.
The whole conditional locking is not required (if my analyses is correct ofcourse) since locks based on the Monitor class are recursive and counted.
There is another problem with the locking mechanism, that is: currently when one thread holds a lock. The second thread wont even wait for the lock but will simply continue without a lock since the lock is conditional! this seems like a big bug!
Regarding the naming convention. I use it myself for a way of differentiating privates from parameters and locals. Its a preference which many C# coding conventions recommend. This helps in a case like this:
void Method(int number)
{
// no need to refer to this since:
//this.number = number;
// can be replaced with
_number = number;
}
I'm not sure if my title is really correct. I've looked around and searched but not found anything so please forgive me if my problem has been answered already.
What I would like to do is call a function but not have to come back to the calling line of code. e.g
public static void temp(obj) {
switch (obj.id) {
case "1" :
if(blah) {
obj.id = "2";
temp(obj);
}
break;
case "2" :
obj.response = "done";
break;
}
}
so basically I dont want to eventually come back to my temp(obj) in the first case and fully pass control. Does this make sense, is it even possible and my architecture is all wrong?
Thank you for your time.
Let me see if I understand the question:
You've got a function Foo(), which calls function Bar(). (I wanted to remove the recursion you had in your example for simplicity, please correct me if that was important.) When function Bar() returns, you want control to pass not back to Foo(), but to Foo's caller?
This is probably possible in lower-level languages, like C, by hacking the stack and not placing Foo()'s return address there, so that when Bar() tried to return, it would jump to Foo's caller instead.
However, in C#, no. The call stack is a stack, and control will pass back in order. The only thing you can do would be to put a return statement after each call to Bar().
Edit:
"recursive calls without them being recursive"
How about this:
bool doItAgain = true;
while(doItAgain)
{
doItAgain = false;
// process, with your switch statement or whatever.
if(...)
{
doItAgain = true;
continue; // if necessary, skip any code after this statement. May not be necessary if you have things set up right.
}
}
If this were C++, you could eliminate the break and let the case "1" fall through, but this is not allowed in C# switch statements.
public static void temp(obj) {
if (obj.id == "1") {
obj.id = "2";
temp(obj);
}
if (obj.id == "2")
obj.response = "done";
}
Do you need the recursive call? This code retains your recursive call and sets obj.response to "done" after changing obj.id to "2". However, obj.response is set twice because of the recursive call. What are you trying to do?
I'm not sure what you exactly intend, but it sounds like a callback to me. Here is one possible example:
void DoSome()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { RunMe(); ReturnTo(); }));
}
void RunMe() { }
void ReturnTo() { }
You start in DoSome() and continue, when RunMe is finished ReturnMe is called.