Jump to content
  • Advertisement
Sign in to follow this  
Munchkin9

C# To Callback or not to callback

Recommended Posts

I've got a problem and I'm not happy with the solution I found, looking for input.

Commands, which serve as passable functions are stored into a queue that gets pulled from on regular intervals. Then they are stored in an EnquedCommand object and placed into a different queue. EnquedCommand contains some info such as where the command is being run from. The second queue is also pulled from on regular intervals. The objects that submit the commands and each Queue are kept separate so they have no easy means of communication. This has worked fine so far.

The problem is I now have a command that is supposed to have the original object that enqued it do something when that command is run in the final queue. But it has no easy means of knowing when that happens.

The solution I found is to embed a callback parameter into EnquedCommand and have that passed through the queues so that the callback is called when the command is run. What I don't like about the solution is that this requires a fair bit of refactoring and, so far, this is the only command that needs one. Seems like overkill.

Are there any other solutions anyone can think of?

Share this post


Link to post
Share on other sites
Advertisement

callback seems fine for this.

or just in the command that needs it, have an additional member variable such as m_command_has_executed with a get_has_command_executed() member function.  Have the original object that created the command maintain a reference to the command.  On the next tick when the object runs its update() method, have it check the last_enqueued_command->get_has_command_executed() to see if it already ran.  but don't see how that is really any much better than a callback function.  just another way.

Share this post


Link to post
Share on other sites

Seems like there are some other potential concerns, such as object lifetimes. Some languages and tools are better suited at this than others, but there are important details like making sure the objects involved are all still valid when commands are run.

I've worked with container-style systems where objects in the container can have their function called at specific future points in time, such as before/after processing, before/after rendering, before/after physics. It is more special purpose than you described, but has the benefit of letting the container verify the object is still alive before calling the function.

I've also seen many event bus systems allow for delayed events to be broadcast. A system can register an event listener and fire a timed event.  If the target object is still alive the object's listener can respond, if the object has died it will have been de-registered as a listener so no problems from running a callback on dead objects.

For the specific problem you're facing a message bus sounds ideal.  The original object can indicate it needs an event with a specific unique ID.  The system can listen for the event, and if the unique ID matches it can do the work it had delayed. The system may need other protections, such as killing off long-overdue tasks, but the message bus pattern solves all kinds of inter-object communications issues.

Share this post


Link to post
Share on other sites
On 12/24/2017 at 9:10 AM, Munchkin9 said:

The solution I found is to embed a callback parameter into EnquedCommand and have that passed through the queues so that the callback is called when the command is run. What I don't like about the solution is that this requires a fair bit of refactoring

Commands are functions, right?  If they already perform work then why does anything need to be refactored?  Perform the callback within the normal work of the command's function, or wrap the command with a command which calls the original command THEN the callback, if that makes more sense.  Imagine this pattern, but adapted to whatever additional complexities you require (IPC, RPC, etc).

Action WrapAction(Action command, Action callback)
{
  return () =>
  {
    command();
    callback();
  };
}

If you're dealing with IPC then you will definitely need some way of handling responses and completion which can deal with the callback.  It's not overkill.  If you're NOT dealing with IPC then do you really need all those intermediate objects and queues?

Edited by Nypyren

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By bojanzarnoski@gmx.de
      Hello,
      I want to get into coding again by programming a 2D platformer to get started, but i don't know if i should use Java or C# with the unity engine.
      I am pretty fit with Java, but with c# i have to start from scratch. What do you recommend and why?
    • By SickTwistGames
      Ok, firstly, Hi.
       
      This is my first post on this forum. I am an Indie Dev making my first game so bear with me when I say dumb stuff, I'm on a huge learning curve.
       
      My first question is about inventory systems for unity. I am trying to make a survival type game with crafting. I have purchased Inventory manager pro by devdog from the unity asset store and it seems like a pretty powerful assett but for an intermediate coder its a little tough to use.  I'm beginning to wonder if it was the right purchase.
      So my question is.... does anyone have any experience of inventory plugins / systems for unity and can anyone reccomend a system to me?
      It needs to have the following: Loot system, crafting system, character sheet, blueprint system,  character stats system. Ideally with as little coding as possible.
       
      Thanks
    • By ethancodes
      I've got a bug with my brick breaker style game. The bricks move down one line at a time ever 1.5 seconds. What appears to be happening is occasionally the ball will be just about to hit the brick when the brick moves down a line, and now the ball is behind it. I'm not sure how to fix this. I have two ideas but I'm not sure of implementation. 1 solution would be to check where they were and where they are going to be before rendering the frame. Then if they crossed paths, then register the brick as hit. Solution 2 would be change how the bricks move. I could maybe slide them down line by line, instead of a jump down. I'm not sure of this will fix the issue or not. Any ideas?
    • By Scouting Ninja
      Once again Unity is frustrating me to the point of insanity.
      What I am looking for is a way to find a ray intersect with the edges of the mesh, using Unity's already made collision system. I want to point out that I know how to do a line intersect, what I want to know is if Unity supports this already.

      The image above shows how I sweep a ray,intersecting the mesh. The top green image shows what I want and the red shows what Unity is giving me.
      I want to know if there is some way, to find the edges in Unity without creating a custom line intersection tool.
      Most engines I know don't use rays for this but instead use a plane like this:

      I checked the Unity "Plane intersection" but it is just a ray cast. It will still need me to find the vertices on the collision mesh to cast the ray from; if I am doing that then making my own line intersection tool is better.
       
      I looked online and can find anything on this. Also I don't want to cut the mesh, so I don't need a way to know what side is what.
      Does Unity even have collisions that support edge only detection?
    • By JuliaAxt
      Please help me with this code, this error is currently stopping my project 
      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      [RequireComponent(typeof(Rigidbody2D))]
      public class TapController : MonoBehaviour {
          public float tapForence = 10;
          public float tiltSmooth = 5;
          public Vector3 startPos;
          Rigidbody2D Rigidbody;
          Quaternion downRotation;
          Quaternion forwardRotation;
          private void Start() {
              Rigidbody = GetComponent<Rigidbody2D>();
              downRotation = Quaternion.Euler(0, 0, -90);
              forwardRotation = Quaternion.Euler(0, 0, 35);
        
          }
          private void Update() {
              if (Input.GetMouseButtonDown(0))
              {
                  transform.rotation = forwardRotation;
                  Rigidbody.AddForce(Vector2.up * tapForce, ForceMode2D.Force);   (The name `tapForce`does not exist in current context)
              }
              transform.rotation = Quaternion.Lerp(transform.rotation, downRotation, tiltSmooth * Time.deltaTime);
          }
      }
          void OnTriggerEnter2D(Collider2D col){
          if (col.gameObject.tag == "scoreZone")
          {
              // register a score event
              // play a sound
          }
          if (col.gameObject.tag == "deadZone")
          {
              Rigidbody.simulated = false;   (`Rigidbody` does not contain a definition for `simulated´) 
              //register a dead event
              //play a sound
          }
           }

      }
       
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!