Well, I think your first mistake is to make location decisions based on rotation values.
Vectors are easy to deal with, they are linear and follow each axis in a clean scalar way.
Rotators however have a limited range of values, and once you "overflow" it will turn around, and since they're Euler angles, you will get into gimbal locks.
So the first thing you should do is to never decide camera locations based on a rotation, it will only make things harder for you.
Handle locations with vectors alone, and handle rotations with both (since vectors ease the work with rotators transitions a lot).
Ideally you would want to use quartenions instead, but there's really no need to complicate right now.
The second thing is to handle the rate of change over time with "states" rather than incremental progress.
By "states" I don't mean "UScript states", I mean saving the starting and ending locations/rotations in the camera itself, and then interpolate between both over time.
You're using Velocity and Acceleration, and these will always cause issues, and you will keep patching things up to be smooth, and never quite get there that way.
What you want is a precise way of mathetically go from A to B, regardless if you do it linearly or non-linearly.
Physics in general is very flawed in this engine, since it handles non-linear physics in a linear fashion over time.
There are better ways of doing it, which are as fast to run and follow the real physics equations to the letter, but they depend on the same kind of "states" of change.
In other words, you should use the exact kind of functions I posted in my previous post to update the camera over time directly through SetLocation and SetRotation.
All you need to actually do is refactor your camera code so that:
1 - You have a Start and End location and rotation at all times defined in the class itself (StartLocation, EndLocation, StartRotation and EndRotation) and make them private:
Code: Select all
private Vector StartLocation, EndLocation;
private Rotator StartRotation, EndRotation;
They're private so they can be changed by methods you implement in your class alone, and nowhere else, not even from subclasses (and because they're either public or private, you cannot have "protected" in this engine).
2 - The same for the control of time you want to transition from Start to End (TransitionTime and CurrentTime):
Code: Select all
private float TransitionTime, CurrentTime;
3 - You have nothing more than methods which you call like SetEndLocation and SetEndRotation, for example:
Code: Select all
function SetEndLocation(vector Loc, float Time)
{
StartLocation = Location;
EndLocation = Loc;
TransitionTime = Time;
CurrentTime = 0.0;
}
Same for SetEndRotation.
4 - Then you use the Tick event to update it:
Code: Select all
event Tick(float DeltaTime)
{
local float Alpha;
local Vector RVStart, RVEnd;
local Rotator R;
//time increase
CurrentTime += DeltaTime;
//already finished
if (CurrentTime >= TransitionTime) {
if (Location != EndLocation) {
SetLocation(EndLocation);
}
if (Rotation != EndRotation) {
SetRotation(EndRotation);
}
//transition
} else {
//alpha
Alpha = CurrentTime / TransitionTime;
//location
SetLocation(StartLocation + (EndLocation - StartLocation) * Alpha);
//rotation
RVStart = Vector(StartRotation);
RVEnd = Vector(EndRotation);
R = rotator(RVStart + (RVEnd - RVStart) * Alpha);
//todo: calculate roll as well, a bit more tricky, but easily manageable between "StartRoll" and "EndRoll"
SetRotation(R);
}
}
Something like this.
This is a rough version of what you can do, so it can be optimized and whatnot, but this way you're able to have the smoothest camera you can possibly have, and it's not hard to implement.
From here, you could even modify it so the transitions could be non-linear (accelerate when starting and slow down when ending) and add other features such as detect when it's already at the middle of another transition and adjust the time accordingly.