Following from my previous tutorial, Creating an Orbit Cam for iOS, today we’re going to learn how to drag an actor around a level using touch.  If you haven’t read the previous tutorial, I would recommend doing so before starting this one.

The first thing we need to do is create the class we’re going to move around.  We’ll make a custom class so it’s easier to make the detection code in our PlayerController.

 

Pretty simple here, our Tapped function will let us change the material so the player knows what actor has been selected.  Using the ? : format is easy.  You put the condition you’re checking for before the question mark, then what to do if it’s true or false.  Example:

It’s a more compact way of saying:

Very useful for simple checks.

Now we need to add two variables to our AwesomeMobilePC class.

 

DragActor will hold a reference to the AwesomeMobileActor that we’re moving, and the bool we will use to prevent the camera from moving around while we’re dragging the DragActor.

There is one line we need to add to our SetupZones function, since we’ll be using the swiping motion to move the DragActor instead of a tap.

 

We’ll process our FreeLookZone’s input in our own function, CheckDragActor (click image to enlarge).

 

You may notice that the first half of this function looks a lot like our TapToMoveTap function.  We’re using a trace here to determine whether or not we want to move our DragActor, as well as where we want to move it to.  Inside our ForEach is where most of the work takes place.  We only want to be able to drag the actor when we click on it, if we’re clicking off of it the player may only be trying to rotate the camera.  To do that we’ve added a local boolean, bAllowDragActor.  If our trace hits the current DragActor, we know that the player is trying to move it so we allow it.  Next, we want to move the actor to the “top most” actor’s hit location, not anything behind or below it if we have a level with multiple floors.  We make a variable bFirstHitActor here, and only take the first actor that isn’t the DragActor itself to figure out our hit location.

After we exit our ForEach we know two things:  Whether the DragActor was along the trace the player started so we know they want to move it or not, and whether or not we hit an actor we can move our DragActor to.  If the player doesn’t want to move the DragActor we need to let the camera function know, so we save bAllowDragActor as our class variable bDraggingActor.

Next, if we already know the player doesn’t want to move the DragActor, we should exit the function before we move DragActor.

Finally, if we know the player is trying to move DragActor, then move it to our HitLoc.

Now for a few changes to our TapToMoveTap function.

 

In this function’s ForEach, if we tapped on an AwesomeMobileActor we want to select it instead of moving the camera, so we set the DragActor here and then exit out of the function.  If not, after the ForEach runs we check if there’s a current DragActor, if there is then it means the player has tapped outside of the DragActor and wants to unselect it, so we do that and exit out of the function.  If there’s no current DragActor then we know the player is trying to move the camera, which is the last part of that function.

Now, while we have a DragActor and we’re moving it around, we don’t want the camera to move.  We need to change the two lines in PlayerTick that deal with the player input (click to enlarge):

 

We use more of the ? checks here.  If there’s no DragActor or there is and we’re not moving it, then move the camera.

That just about does it!  Compile the code and open the editor.  We’ll use a copy of the SimpleCourtyard to test this, so save it under a different name and add an AwesomeMobileActor near the center.  Now go to View, open World Properties, and in the World Info tab, set Game Types Supported On This Map and Game Type For PIE to AwesomeMobileGame.  This makes sure that the script file makes it to the iOS device.  Save the map.  Now, double check that you have the gametype set in your MobileGame\Config\DefaultGame.ini like this:

 

And that you have your RequiredMobileInputConfigs set up in the same file:

 

 

If not, close the editor and make the changes to your DefaultGame.ini file.  Reopen the editor and run the test map.  You’ll notice you can tap the actor to select it, drag it around the screen, move the camera around while you have it selected, and unselect it by tapping away from it.  We’re good to go!

 

Now for your challenge.  You’ll notice when you drag the actor it snaps to the touched location before following your finger.  Try using a vector to save an offset to get rid of the snap.  Have fun!

Download the source files for this tutorial.

12 Responses to “Dragging an Actor on iOS”

  1. hany says:

    Great tutorial, thanks for the effort, waiting for more :)

  2. Hugh says:

    Thanks a ton for these tutorials! They’re very helpful.

    I’ve followed all three of these (Creating Framework, Creating Orbit Cam, and this Dragging Actor tut), but with this Dragging Actor tutorial, I cannot seem to grab a static mesh. My code compiles fine and my camera seems to work as desired too, so I’m not sure what the issue would be.

    Any input would be greatly appreciated. Thanks in advance and thanks again for these!

    Insipidus

    • Rachel says:

      Are you tapping on the actor to select it before you try to drag it? I might not have made that clear enough in the explanation. If tapping on it doesn’t work, then it’s time to add logs to make sure all the functions are being called. After the local variable lines, add a line like this to check if the function is being called:

      `log(“SomeFunction has been called!”);

      Then run the game, close it, and check Launch.log in the MobileGame\Logs folder (or Launch2.log if you were running the game from the editor). You can also use this to check actors, for instance if you put this inside the foreach Pawn.TraceActors call in the TapToMoveTap function:

      `log(HitActor@”<– This is the HitActor”);

      It will log every actor along the trace when you tap. Run the game, tap on the box, then exit and check the log to make sure the AwesomeMobileActor is one of the HitActors. Let me know if this helps!

  3. Gauji says:

    Dude these are really amazing, Do not stop making these, you are making very high quality tutorials! i will be coming again and again to see if you have more !

    - G

  4. Artsog says:

    Phenomenal!! Nobody else is explaining these things on the net. Thank you VERY much

  5. Artsog says:

    Ah, I have a little question.
    When I attempt to drag my actors, the Orbital Camera seems to kick in before I can drag my actor, so in other words if I drag too fast, I cannot move the actor, because the camera interrupts it

    Any idea if I did anything wrong?

    Thanks again for this!

    • Rachel says:

      The way I have this set up, first you tap on the actor to select it, then you can drag it. If you want it to immediately select and start dragging, I’d move the trace code from TapToMoveTap into CheckDragActor, using the EventType of ZoneEvent_Touch to detect the first touch. Have fun and I’m glad this helped! :)

      • Artsog says:

        Yowch!

        I kind of understand the concept, but I will admit, you’re talking to a n00b, I’m not sure exactly how to go about this, I’ve tried a few things. And if I believe I also have it set up as you, where you must tap it once to select first, then tap again and drag to move it. I suspected it had something to do with the TapToMoveSmoothFator , but It seems I’m wrong, when I change this value all that happens is the camera gets closer or farther from the origin, and that is all…. :( Don’t mean to be a hassle here!

        • Rachel says:

          No, the TapToMoveSmoothFactor was explained in the previous tutorial, it controls how fast the camera moves towards a tapped position. These tutorials weren’t really meant for beginners, but I’d read through all three of them carefully to understand how everything functions, what each line is doing and why.

          I can’t write the code for you, but I’ll be glad to help you help yourself figure it out. Read through the tutorials again and then read my previous post, hopefully it will make a bit more sense. :)

          • Artsog says:

            Alright! Well I’ve read through the tutorial, and yes I got it figured out, it works as desired, I made a few minor tweaks too :)

            So now I’m working on getting the tap to move to only move on a path (as if the camera were on a track and could only move lets say, along the X or Y axis relative to the floor), making it so i could keep my map “centered” in relationship to the Viewport and only moving forward or backwards

            In fact, I don’t even care so much for understanding how to constrain it, I’m more concerned with finding a way to limit which objects the tap has to hit to set off the TapToMove

            Now, you’ve been kind enough to help me so honestly, I am very thankful as it is, I’m looking for a push in the right direction, but feel free to tell me to go away , I love learning, but I hate abusing other people’s kindness

  6. Rachel says:

    Oh no problem! I’m glad you were able to figure it out.

    To limit what can be tapped to move you would work inside the trace part of the TapToMoveTap function, similar to what it’s already doing to select the custom actor. Think about how the HitActor variable is being used.

  7. Lex says:

    Hey, thanks for the great tutorial.

    Is there any chance of you making a tutorial on how to move objects to tap location (like in a point and click game – but for mobile)? I’m really getting lost trying to write the code for it.