Sorry for delay. I got sick last week and am still recovering. But I have answers.
-
First of all:
Onward to describe things I found that needed fixing in your project:
-
Your application had effectively 2 instances of TCastleThirdPersonNavigation
. One is ThirdPersonNavigation
, the one you have designed in editor, and another is ThirdPersonNav
, the one you have created at run-time. They will both try to control the camera – it will not work OK.
I did mention this before in the past threads (that you will have to configure all your navigation at run-time), but all in all I think that this approach is just too difficult. I decided to simplify it for you by making it easier in the engine – you don’t need to create TCastleThirdPersonNavigation
descendant anymore.
So, new advise: just remove your TThirdPersonNav
from your code. Remove the ThirdPersonNav
local variable from Start
. Remove also the global ThirdPersonNav
, this was unused (only confusing to humans, and not used by the compiler for anything since you obscured it by local variable). Remove these lines from Start
:
ThirdPersonNav := TThirdPersonNav.Create(FreeAtStop);
MainViewport.InsertBack(ThirdPersonNav);
Instead, use the one and only one navigation you made at design-time: ThirdPersonNavigation
. To configure animations, assign in view Start
:
ThirdPersonNavigation.OnSetAnimation := @NavigationSetAnimation
and define in your TViewMain
class a private method
procedure TViewMain.NavigationSetAnimation(const Sender: TCastleThirdPersonNavigation;
const AnimationNames: array of String);
begin
end;
Forget about creating descentdant of TCastleThirdPersonNavigation
, this is too difficult. You will only need to implement the method NavigationSetAnimation
, which can be a method inside your existsing class TViewMain
, this should be much simpler.
A sample implementation of NavigationSetAnimation
(but this is only a sample – you have to finish this, only you know the details of what animations you have on your model and when to play them!) would be to control SceneLegs
animation based on whether the animation is idle
or not. For this, put
SceneLegs: TCastleScene;
in the published
section of your TViewMain
. Implement NavigationSetAnimation
like this:
procedure TViewMain.NavigationSetAnimation(const Sender: TCastleThirdPersonNavigation;
const AnimationNames: array of String);
begin
{ Example implementation that merely sets animation on SceneLegs,
to either TORSO_IDLE or TORSO_RUN.
Use castle-model-viewer (formerly view3dscene),
https://castle-engine.io/castle-model-viewer,
just double-click on MD3 file from CGE editor, to see available animations
(in "Animations" panel).
}
if AnimationNames[0] = 'idle' then
SceneLegs.AutoAnimation := 'TORSO_IDLE'
else
SceneLegs.AutoAnimation := 'TORSO_RUN';
end;
If this sounds difficult, remember you have a working example where I did all above from Various fixes described in forum thread by michaliskambi · Pull Request #2 · JPF12141999/Toy-Story-2-Ripoff-Game · GitHub .
-
You need to set PreciseCollisions
to true
on Scene1
. The camera (used by TCastleThirdPersonNavigation
) is using this (old) system for collisions. See Physics | Manual | Castle Game Engine .
This need may be removed in the future Castle Game Engine versions. Your scene (Scene1
) already has TCastleMeshCollider
, this is good and shall be enough. But for now, you also have to set Scene1.PreciseCollisions
to true
. (it’s just a checkbox in the editor, just click it, you don’t have to actually set it using Pascal code.)
Doing this unblocks normal camera orbiting around the avatar and zoom in/out using the mouse wheel.
As a bonus, this also makes working in editor better. Setting PreciseCollisions
to true
on Scene1
allows to easily pick objects when working in CGE editor.
-
As your AvatarTransform
has non-standard rotation, you have to set
AvatarTransform.Orientation := otUpZDirectionX;
from TViewMain.Start
method in your code. Also declare
AvatarTransform: TCastleTransform;
in the published
section of your TViewMain
. As you will see, this solves the major problem with both camera orbiting and avatar movement. The default orientation assumes you have “up” in +Y and “forward” in +Z, which was completely wrong and resulted in all sorts of weird transformations for your model. Using otUpZDirectionX
makes almost everything OK
-
You didn’t call Init
method of the navigation. See the API docs ( Castle Game Engine: CastleThirdPersonNavigation: Class TCastleThirdPersonNavigation – “Call Init once the parameters that determine initial camera location are all set.”), we explicitly require calling this method to make initial camera sensible.
In the end, this is Start
method contents that work for me (note that this code block may have extra scrollbar, be sure to see it all):
procedure TViewMain.Start;
begin
inherited;
{ Critical to make camera orbiting around and movement of avatar
to follow proper direction and up.
In the AvatarTransform local coordinate system,
the avatar is moving in +X, and has up (head) in +Z. }
AvatarTransform.Orientation := otUpZDirectionX;
ThirdPersonNavigation.MouseLook := true;
ThirdPersonNavigation.OnAnimation := {$ifdef FPC}@{$endif} NavigationSetAnimation;
{ Configure parameters to move nicely using old simple physics,
see examples/third_person_navigation for comments.
Uncomment these if you decide to move using "direct" method
(when AvatarTransform.ChangeTransform = ctDirect,
or when AvatarTransform.ChangeTransform = ctAuto and
AvatarTransform has no rigid body and collider). }
AvatarTransform.MiddleHeight := 0.9;
AvatarTransform.GrowSpeed := 10.0;
AvatarTransform.FallSpeed := 10.0;
// a bit large, but it is scaled by AvatarTransform scale = 0.1, making it 0.5 effectively
AvatarTransform.CollisionSphereRadius := 5;
ThirdPersonNavigation.Init;
end;
-
You put TCastleMeshCollider
on the avatar (as behavior of AvatarTransform
). This is not good for a moving object – TCastleMeshCollider
is static (see Physics | Manual | Castle Game Engine , “”“TCastleMeshCollider (using this collider forces the body to be static)”“” ).
It also had Mesh
unassigned, making it additionally not useful.
To resolve collision with avatar using physics, you can use physics collider like TCastleBoxCollider
. You can use “Change Class” context menu option in CGE editor to do this. See also how CGE examples/third_person_navigation
has it set up. As in that example, set also LockRotation
on avatar to [X,Z], to only allow avatar to rotate around Y (world up axis).
… But actually, I will propose a different solution now:
Remove from AvatarTransform
rigid body and collider. This will make the avatar not affected by physics, and it will be controlled by TCastleThirdPersonNavigation
directly. This is the simplest solution for avatar. You could alternatively explicitly request it setting AvatarTransform.ChangeTransform
to ctDirect
.
We have alternative navigation components coming in Castle Game Engine, since a few months now, with better physics integration. Right now, with TCastleThirdPersonNavigation
, it seems easier to just recommend to not use physics for 3rd person avatar. (the physics can still work in the world otherwise, of course, just not for the avatar itself.)
-
Default speed is slow, it is applied in local transformation system and your AvatarHierachy
has scale = 0.1. Set MoveSpeed
to 10 on ThirdPersonNavigation
to make nice speed.
-
There are still some images that are being referred to using absolute paths that only work on your computer: file:///C:/Users/Joshua/Pictures/toystoryimages/level1_background/front.jpg
. Seems like they are at background. They will not work on other systems, refer to them using castle-data:/..
.
-
There are a lot of textures that don’t have power-of-2. They are resized to have power-of-2 at runtime (this is necessary to have something called “mipmaps” which makes textures in 3D look good regardless of from what distance/angle you view them). You can make things load much faster by already providing textures in sizes that are power of 2.
Note that your textures are embedded in GLB files, so admittedly the log is a bit obscure:
Textures: Resizing 2D texture "" from 474x316 to 512x512
Textures: Resizing 2D texture "" from 474x632 to 512x1024
Textures: Resizing 2D texture "" from 474x632 to 512x1024
We tell you that size is wrong, but we don’t tell what is the texture, all textures are named “” in this case. I know this is not very helpful, I’ll think how to improve this in the future.
Note that, while we handle GLB, we generally advise to use separate glTF + textures (see Blender | Creating Game Data | Castle Game Engine ), then textures are in separate files (like png, jpg) and you can easily see what is resized.
-
You have some Wavefront OBJ with invalid materials, Warning: Wavefront material "cannon_puffer_jf" specifies specular exponent (Ns) as zero, ignorin
.
-
There are a lot of warnings Warning: Using non-uniform scale 5 1 5 for physics body (collider MeshColliderOil) is not fully supported
.
Do not ignore them, unless you don’t want to use physics in the end. You really cannot use such scale with physics bodies, physics engines do not cope with non-uniform scale and results are undefined.
“Non-uniform” means that scale is different in different directions. E.g. scale “2 2 2” is OK (uniform), scale “2 1 2” is not OK (it is not uniform).
You have to scale objects in a different way. If this is on a mesh, then mesh vertexes have to be scaled (in Blender: “Apply Scale” operation does it). If this is a TCastleBox, then you should scale it by changing TCastleBox.Size
instead of Scale
. There is no universal solution, it depends on what you are scaling, but it is important that you avoid non-uniform scale on objects that are used with physics.
This is a common limitation of physics engines.
-
In your new project upload, you didn’t add .gitignore
file. I recommend you add it, to avoid committing by accident stuff that should not be committed. Sample contents of .gitignore
:
# Files ignored by GIT version control
# Build tool (and compiler) temporary output
castle-engine-output
# Unix executable
toy-story-2-like-game
# Windows executable
toy-story-2-like-game.exe
# Library files placed alongside Windows executable
*.dll
# Auto-updated by CGE tools when compiling Windows build
castle-auto-generated-resources.res
# May contain secret data (your Android keystore username and password)
AndroidSigningProperties.txt
-
Looking at commit logs, you seem to do a lot of things to “file upload” on GitHub. That’s an option, but it’s not very convenient way to synchronize your project in the long run. Use rather a proper “GIT client”, I recommend https://desktop.github.com/ which has a good set of features while maintaining a simple user interface.
-
Submarine
component, child of Workshop_Submarine
, has rotation with zero axis but non-zero angle: 0 0 0 deg(90)
. This is causing warnings
RotatePointAroundAxisRad called with rotation Axis = zero...
You can fix it by just setting Submarine
rotation to exact zero, 0 0 0 0
. Pratically, you can also ignore this warning, it doesn’t mean any real problem in this case. (I’ll think whether to maybe just ignore these things in next engine versions, i.e. be silent instead of making warning.)