Ok! Like I promised, I'm back with another article after finally getting movement between adjacent walls and aiming in cover working. Vaulting will be next, though that's kind of a tricky one to do without having any commissioned animations yet >_>
I've put together another video that shows the major additions, which you can see below:
Alright, now where should I begin...
A Major Headache
First, let's talk about a major headache I had. These articles are supposed to be my documentation as much as anything, so I think it's worth touching on this even though it has no bearing on my final implementations.
Basically, I was minding my own business, trying to get the character to move to another wall without it being either messy in code or awkward-feeling in game. As I was just about to take a break, Visual Studio asked me to update. So, being the good citizen that I am, I obliged.
When I came back, it was like everything just broke. Replication wasn't working for the Listen Server. My client's motion was super jittery anytime I used the MoveComponentTo function (cover sliding, rotating back into position after aiming in cover, etc.) I was completely flabbergasted! I reinstalled VS. Reinstalled Unreal Engine 4 (not a good time). Started making logs of the Client vs. Server positions each Tick... I mean, look at this nonsense:
This log shows the location data reported each tick by Client and Server during a slide to cover. The Client is like 15 - 25 cm behind the Server except at the end of the movement! Awful!!! Edit: Can I mention that I just noticed I spelled "Server" as "Sever?" You can tell how psychologically disturbed I was by this point.
Oh, but I will say I verified something I thought I knew but never conclusively determined before, which is that the Character Movement Component does NOT replicate explicit rotational changes. I won't show the log here to save space, but if you only run the function to set rotation on the server, the client doesn't change their value at all. If you set location, however, they do. Useful thing to know!
Anyway, after TWO DAYS of this nonsense, I find the problem... at the VERY TOP of my code:
WHY IS IT FALSE?! I DIDN'T. SET IT. TO FALLLLSSSEE ZSFOJOJOWE! *throws keyboard at cat*
...*clears throat* Yes, well, that was the problem. The MoveComponentTo function needs you to Tick, and my character wasn't ticking. As soon as I turned it on, all my jittering went away. Pro tip :)
NOTE: I only set Tick enabled right before and after a MoveComponentTo function. DO NOT TICK ALL THE TIME THAT IS BAD AND YOU LOOK LIKE A N00B.
Moving Between Adjacent Walls
Now that that's out of the way, on to happier topics! I had mentioned in my previous DevLog that one of my ideas was to move the actor to a CollisionBox on overlap and set their new rotation based on its ArrowComponent direction. It was the idea I said I was less fond of due to wanting to keep control in the players' hands, but I changed my mind for three reasons: 1) It's cheap and relatively easy to do, 2) The time to move doesn't noticeably interfere with player movement, and 3) It gives that motion just a slight feeling of "purpose", like there's some intent behind switching walls... which I think I might use to my advantage when designing levels (more on that later)...
So yes, the implementation itself isn't horribly complicated. There are a decent number of checks I have to do to handle things like aiming, is it high cover or low, is the player trying to get out of cover, etc., but the fundamental idea is simply:
- When the player overlaps a CollisionBox, check to see if the forward vector of its ArrowComponent equals the one of the previous box. If not, it's an adjacent wall.
- If it's an adjacent wall, use MoveComponentTo to set the player's location and rotation to the new wall over a short period of time. Adjust this time to be smaller based on player speed so that the motion feels consistent whether walking or sprinting.
And that's it, really. You can see the results without the CollisionBoxes showing in the video at the top of the article!
Aiming In Cover
You know, there are some intricacies to this aspect of cover that I hadn't fully thought of before starting to implement it, and as a result I'm not completely done with even the basic implementation. But I do have most of the basics down:
- The player can aim while in cover.
- The direction vector calculation is updated when the player aims so that it feels just the same as when they're not aiming; they can move right or left in cover by inputting directions that make sense intuitively based upon where the camera is pointing.
- The player can back out of cover while aiming and put themselves into a "Not In Cover" state.
- The player automatically rotates into a position that feels natural when releasing the aim button while in cover. For example, if they got into cover facing to the right, aim to the left, then release the aim button, they will now be facing to the left. This ONLY applies when the player is NOT moving, because when moving it's more natural to rotate back in the direction of movement, regardless of which way we are aiming.
- When moving in cover, if the player reaches a piece of high cover, they will stop aiming automatically.
And that's what I have so far. Like I mentioned, there are some other details that I also need to deal with. For example...
- How far over cover can the player shoot? Can they look all the way down behind the other side of cover? Will that depend on the type of cover?
- If a player is in high cover, should they be able to aim behind them while still in cover? Should we automatically take them out of cover when they try to aim in the opposite direction of the wall's normal?
- Do we allow the player to hold the aim button while sliding into cover and automatically start aiming? Should they have to time the button press properly to aim only after the slide is complete? Should aiming cancel the cover slide?
...And a few other questions, but those are the main ones. The top one is the one I'm going to be most focused on right now. I don't think they can see far enough over at the moment because I'm not shifting them forward at all when they aim, so I'm going to try getting that worked on so they can see most of the way on the other side of cover (remembering my principle from DevLog #2: No Over-Powered Cover!)
I'm mostly in new territory now. The furthest I got on a similar project, which I started... oh, 3 years ago now?... was here, minus being able to move to adjacent walls. And I had some of the actions at cover edge figured out, just not super well. That said, I anticipate that finishing the cover system, even if I'm only working through the basic logic at the moment, should be quite the journey indeed.
However, I absolutely plan to come out alive on the other side and not fall into the deep, dark pit that many indie devs fall into, never to be seen or heard from again... but of course, we all say that don't we ;)