Summer Work (Day 6)
Big success
Over a week since I started this project I have finally achieved orbiting planets! All scripts compile without warnings or errors and the simulation works as intended.
The major problem I was dealing with yesterday was with UObjectIterator. It ended up, not surprisingly, being user error rather than the engine being broken. The just of the problem was that I was trying to get pointers to actors in the world, which is not possible with this iterator and as I later found out, not necessary. I found that there was also TActorIterator which has some differences that I don't understand but which are better for my use. Basically, the code had to go from this:
for (TActorIterator<ACelestialBody*> Itr(GetWorld()); Itr; ++Itr) {
bodies.Add(Itr);
}
To this:
for (TActorIterator<ACelestialBody> Itr(GetWorld()); Itr; ++Itr) {
bodies.Add(*Itr);
}
Moving a single * solved the problem. So as I understand it, instead of trying to get pointers to the actors, we are instead getting references to the actors and converting them to pointers when we add them to the array of pointers.
Interesting note here, before I switched to using the actor iterator from the object one, I tried to print the value of the celestial body that was updated it returned this:
Apparently this is what happens when you try to get the direct value of an actor and not its name.
So at this point the code was compiling with no errors for the first time. I decided to run the game with two planets in the scene to see if it would work. Answer... no.
The editor froze for a few seconds then crashed. It took me some time to figure out what was wrong. I eventually remembered the debug feature that VS has where it will tell you of any unhandled exceptions that were thrown (something that crashing unreal did not do). Doing this gave me the place where the editor was having issues. It turned out it was with the UpdateVelocity function on the CelestialBody.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void ACelestialBody::UpdateVelocity(TArray<ACelestialBody*> allBodies, float timeStep) { for(int i = 0; i < allBodies.Num(); i++) { ACelestialBody* otherBody = allBodies[i]; if (otherBody != this) { float sqrDst = (otherBody->GetActorLocation() - this->GetActorLocation()).Size(); FVector forceDir = (otherBody->GetActorLocation() - this->GetActorLocation()).GetSafeNormal(); FVector force = forceDir * gameMode->gravitationalConstant * this->mass * otherBody->mass / sqrDst; FVector acceleration = force / this->mass; this->currentVelocity += acceleration * timeStep; } } } |
On line 10 it needs to multiply by the gravitational constant that is held in the gamemode. The problem with this was that gameMode was nullptr and so the whole editor crashed. I then added to the if statement a check to make sure the gamemode existed. The editor didn't crash anymore but the planets also weren't moving because that part of the script wasn't running. I had three ways of solving this: 1) set the gameMode in BeginPlay for each celestial body, 2) set the gamemode on each celestial body from the game mode when it adds the bodies to its own array, or 3) just hardcode a number for the gravitational constant.
I had already tried number one and that resulted in the nullptr error so I went on to 2. I tried this:
for (TActorIterator<ACelestialBody> Itr(GetWorld()); Itr; ++Itr) { bodies.Add(*Itr); *Itr->gameMode = *this; }
This had no red squiggles but errored out when I tried to compile. The error had to do with an "unresolved external symbol". I tried googling around for a solution but all I found was people adding third party libraries and not adding a new public dependency module to the Build.cs. Because I could not find a way to fix this I resorted to the third option.
I plugged in 100 to test, started the editor, and voilà; orbiting planets! I was actually so excited to see this finally work I actually pumped my fist in the air. I played around with this for some time, messing with moons, moons of moons, solar systems, and other wacky configurations. I now see just how important those debug lines are from the Sebastian Lague's project. That will probably be the next challenge, but as of right now I have no clue how I'm going to do it.
Here's one test of a planet with two moons:
Comments
Post a Comment