How do I stop return to player camera after a level sequence?

I posted this on the answerhub and haven’t gotten any advice, so I figured I would try here. This is the original post from the other forum -> How do I stop return to player camera after a level sequence? - Cinematics & Media - Unreal Engine Forums

So, this is going to take a bit of explaining, I will try to provide all the information I can. I am working on a “serious game” in UE 4.22 that is intended to be used as a training system for school teachers and coaches to use to understand and respond to student-athlete concussions. The game consists of 2 primary play modes, third person control of a teacher walking through a school environment, and Level Sequences/cinematic with UI button choices that the player needs to make. The choices cause branching/alternating level sequences to play. For example, the player may be presented with 2 options, do option X or do option Y. X will drive the game to run 1 level sequence, and Y will drive us to a different level sequence. There is an overall controller present in the levels that maintains current state, and determines which level sequence to load based on user interaction. We use events fired in the level sequences to tell the controller when the sequence is ending, then the next sequence is queued up and played.

My issue is that between the time one level sequence ends, and the next starts up, then engine returns control to the player momentarily forcing the camera back to the third person character camera for a short period of time before the next sequence loads. It is probably less than 200ms that this occurs for (more likely less than 100ms on most average powered machines). It doesn’t sound like a big deal, but it is very jarring. The quick flash of a different camera view is like a strange subliminal message, and is very undesirable since our target audience is non-gamers. It’s actually quite illuminating now seeing video recordings of the issue. The CEO of our company has been saying for months that he sees odd things all over the place, and my team and I have been dismissing it saying we don’t. Well I think the issue is that we are used to lots of visual feedback from years of gaming, and he is not a gamer so to him it is objectionable, but to us it’s just another blip of information.

Here is an example of one of our level sequences:

The Level Sequence has an EndScene event towards the end. That is the selected one in the screenshot. The following diagram explains the flow of events.

FYI, I inherited a lot of this code from the previous lead developer when I took over the project a few months ago. I can speak to what is happening, but not always about why it is done this way. At this point, we are nearing our planned Alpha phase, and major re-work is not in the cards. We are a small start up with limited funding, so we are sort of stuck with the existing architecture. It may well be completely fine the way it is, but I just wanted to add that disclaimer for info purposes.

Here is an example of the Level BP waiting for the event and calling the SR Controller:

290604-levelbp-endscene.jpg

Here is the SR Controller End Scene starting the next sequence:

And this is the Scene Controller actually determining the next sequence to load and starting it:

My assumption about what is happening is that the event handling is asynchronous, and the engine is returning control to the player, so switching the viewport back to the thirdperson camera, while the Level BP/SR Controller are processing the event and queuing up the next sequence. Is there any way to do this better?

Some thoughts I had:

  1. Can I stop the camera from switching back to the third person camera unless I explicitly ask for it? It would be better if the game would leave the Level Sequence camera until the next sequence is loaded.
  2. Can I add a blackout or something to the viewport? Essentially creating a fade in / out effect? This would have to persist over all cameras during this transition period.

I am open to any suggestions at this point. I really appreciate any input that anyone has for this.

Thanks a lot! Fitz

I’m not seeing exactly where the camera is switching back after the sequence ends. Does your sequence have a camera cut track and so it’s actually sequencer that’s taking control of the camera and releasing it? If that’s the case, you can prevent sequencer from releasing the camera by right clicking on the camera cut section and choosing Properties->When Finished-> Keep State.

It doesn’t work. The Sequencer camera is switched to the game camera at the end of its movement.

I know this qustion has been posted a long time ago but I will answer in case anybody needs it in the future.

There are actually 2 things to do :

  • Set your Camera in KeepState mode in order for it to be kept as the view target after the sequence ended
  • Set the “Spawned Object Owner” of your camera to “External” so that Sequencer will not try to destroy your spawned camera, you have to do it yourself. (You can also convert the camera to a Possessable instead of a Spawnable for that)

I hope this helps :slight_smile:

4 Likes

That solved my problem. Thanks a lot!

Hi, I also found a solution for this problem in case someone is still struggling with it.

First of all I want to describe what happens:

After the Level Sequence is finished, the
UpdateCameraCut(UObject* CameraObject, const EMovieSceneCameraCutParams& CameraCutParams) function of the ULevelSequencePlayer is called with a nullptr for the CameraObject parameter.

If the CameraObject equals nullptr, the function tries to find the last used camera before the Sequence was played, which is normally the player character. That is why the camera jumps back automatically after finishing the sequence.

Now the solution is creating a new class based on LevelSequencePlayer and function as follows:

void UMySequencePlayer::UpdateCameraCut(UObject* CameraObject, const EMovieSceneCameraCutParams& CameraCutParams)
{
	if (!CameraObject)
	{
		return;
	}
	Super::UpdateCameraCut(CameraObject, CameraCutParams);
}

We then can use our newly created class as follows:

SequencePlayer = NewObject<UMySequencePlayer>(this);
SequencePlayer->Initialize(SequenceAsset, GetLevel(), FLevelSequenceCameraSettings());
if (SequencePlayer)
{
	SequencePlayer->Play();
}

this way there is now cut back to the player.

I hope it helps someone.

Cheers.

1 Like