pmndrs / ecctrl Goto Github PK
View Code? Open in Web Editor NEW๐น๏ธ A floating rigibody character controller
License: MIT License
๐น๏ธ A floating rigibody character controller
License: MIT License
I have a scenario where I need to implement multiplayer online functionality. I will use socket to synchronize players' state information to a local store named players: new Map(). Can I directly use this players data to drive the Ecctrl component for updates?
When I go into first person perspective, and move the mouse around, often the camera/character rotate.
const MyEcctrl = forwardRef(({ children, pos, perspective = THIRD_PERSON, props = {} }, ref) => {
return <Ecctrl
ref={ref}
dampingC={0.1}
floatingDis={1.5}
autoBalance={false}
animated
position={pos}
jumpVel={0}
{...(perspective === FIRST_PERSON ? {
camInitDis:-0.01,
camMinDis:-0.01,
camFollowMult: 100,
turnVelMultiplier: 1,
turnSpeed: 10,
mode: "CameraBasedMovement"
} : {})}
{...props}
>{children}</Ecctrl>
})
Here's my code.
Any idea how to stop this bug?
I have been able to implement this to my component, and it works brilliantly. I'm very grateful for this!
I have a question though, since my current implementation works only with keyboard controls.
is there a way to implement it for phones and other touchscreen devices that don't use keyboardcontrols ? I hope my question makes sense.
Thanks so much for making this character control available, it's exactly what I've been looking for!
However I am having one issue, which is that the character is endlessly floating.
When applying friction={1}
to the floor, then the Character will stop moving, but I am not sure if this is the right way to handle it, since this will also impact the walking or running speed.
Here is a codesandbox showing the issue: https://codesandbox.io/p/sandbox/test-ecctrl-mqc2t6
Appreciate any feedback!
Here's my App.jsx render jsx.
I tried setting position on the CharacterModel but it doesn't move the camera position.
How would I change the playable character's initial starting position?
Thanks.
<div ref={ref} style={{ width: "100vw", height: "100vh" }}>
<EcctrlJoystick buttonNumber={5} />
<Canvas
shadows
linear
flat
onPointerDown={(e) => {
if (e.pointerType === "mouse") {
e.target.requestPointerLock();
}
}}
>
{!inView && <DisableRender />}
<Perf position="top-left" minimal />
<Environment background files="/meadow_2_4k.hdr" />
<Lights />
<Suspense fallback={null}>
<Physics timeStep="vary">
<KeyboardControls map={keyboardMap}>
<Ecctrl debug animated>
<EcctrlAnimation characterURL={characterURL} animationSet={animationSet}>
<CharacterModel />
</EcctrlAnimation>
</Ecctrl>
</KeyboardControls>
<Map/>
{/* <Ocean/> */}
</Physics>
</Suspense>
</Canvas>
</div>
)
}
I suggest having a way to keep the camera in the primary scene. As discussed here: https://discord.com/channels/740090768164651008/1162488856088690879/1239947711696863316
There is a issue where Ecctrl takes out the camera, therefore we cannot use const { camera } = useThree(); camera.position and trust the position is the same as it's moving with Ecctrl.
This also breaks the whole workflow on pmndrs/uikit as it depends on using the camera in the scene.
given:
import { Html, KeyboardControls } from '@react-three/drei';
//...
<Canvas shadows>
<Html occlude={"blending"} scale={.1} transform position={[.43,2.52,-5.18]}>
<div style={{transform:"scale(1)"}}>
<h1>Let's Go!</h1>
</div>
</Html>
<Physics timeStep="vary">
<Suspense fallback={null}>
<KeyboardControls map={keyboardMap}>
<Ecctrl debug>
<CharacterModel />
</Ecctrl>
</KeyboardControls>
<Room04/>
</Suspense>
</Physics>
</Canvas>
you can not look around in the scene with mouse or pointer. How can we fix this? Any ideas?
Here's my component:
import { useFrame } from '@react-three/fiber'
const Respawn = ({ ecctrlRef, setPos, levelPos }) => {
useFrame(() => {
if (ecctrlRef.current) {
try {
const { y } = ecctrlRef.current.translation()
if (y < 0) {
// this random hack ensures position is reset
setPos(levelPos.map(a => a + Math.random() * 0.02 - 0.01))
}
} catch (err) {
console.warn('error in getting ecctrl translation', err)
}
}
})
return null
}
export { Respawn }
And I'm getting this in the console:
Respawn.jsx:13 error in getting ecctrl translation Error: null pointer passed to rust
at I3.wbg.__wbindgen_throw (chunk-GZS6NCTV.js?v=4fa056a0:2477:13)
at 0057ee2e:0x14f24a
at 0057ee2e:0x14f257
at 0057ee2e:0x11b55b
at _AA.rbTranslation (chunk-GZS6NCTV.js?v=4fa056a0:1811:18)
at lA.translation (chunk-GZS6NCTV.js?v=4fa056a0:2650:26)
at Object.current (Respawn.jsx:7:41)
at render$1 (chunk-PEHQA6ZE.js?v=4fa056a0:17451:22)
at loop (chunk-PEHQA6ZE.js?v=4fa056a0:17474:19)
The player does respawn in the level so the code works mostly, but it's strange it's throwing the null pointer error.
Thanks.
The repo: https://github.com/SadmanYasar/portfolio_2024
Site: https://portfolio-2024-mauve.vercel.app/
On desktop it works fine but on mobile version, the model starts to shake and spins uncontrollably if I zoom in even a little bit. The configs are somewhat default except the physics timestep is set to "vary" and the plane (a boxgeometry) has ccd enabled. I have tried tweaking these settings but still the same issue. What could be causing this?
Is it possible somehow to use these controls to realise something like a spaceship. So that without using a Floor the character won't endlessly fall and finding a way to control the spaceship on all three axes, so that it can go right, left, forward, backward and additionally up & down.
I could imagine this that instead of the Jump controls, there could be two keys (or buttons on mobile) for up & down movement.
Thanks for the great library!
When I run two Three.js scenes on the same page,
your <Ecctrl>
reacts to events coming from the other scene.
This happens because you document.addEventListener
in useFollowCam.tsx
.
Could we optionally provide an alternative root element?
Hi,
I am excited to use ecctrl, however I am getting the following error when importing the module.
Type error: Could not find a declaration file for module 'ecctrl'. '/Users/konstantinlackner/Dev/konchord-experience-demo/node_modules/ecctrl/dist/Ecctrl.js' implicitly has an 'any' type. Try npm i --save-dev @types/ecctrl if it exists or add a new declaration (.d.ts) file containing declare module 'ecctrl';
I tried npm i --save-dev @types/ecctrl
but it is not in the npm registry.
Any idea how to fix this?
Hi! Wanted to test this package but got an error when simply import Ecctrl
Uncaught SyntaxError: The requested module '/node_modules/.pnpm/[email protected][email protected]/node_modules/use-sync-external-store/shim/with-selector.js?v=ed71c189' does not provide an export named 'default'
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
Any suggestions, would be highly appreciated
In my project, I have html components that open on top of the scene. But the character continues to move if I press the keys. Is it possible to disable them?
I have a custom component which i use as my character for the child as shown below, how do I set a custom initial position for this? I tried using the camTargetPos prop but it moved only the camera and not the player. i tried changing the position of the mesh of my player component but whenever I move it it flies off or falls off infinitely. I hope you can help me out with this.
<Ecctrl
ref={playerRef}
floatHeight={0.05}
maxVelLimit={4}
jumpVel={4}
capsuleRadius={0.35}
capsuleHalfHeight={0.105}
>
<Player />
</Ecctrl>
This is the mesh for my player component:
<mesh
ref={head}
geometry={bowlCoverGeometry}
position={[0, 0.01, 0]}
scale={[0.6, 0.6, 0.6]}
>
<meshBasicMaterial color="sienna" />
</mesh>
I love this library and it's working great for me with the project i'm building. However I want to be able to access my meshes position / translation information to know its coordinates. So that if it falls for example, I can reload t=it back to its initial positoin. However I can't seem to get access to this data, is there a way to get this ?
Where my mesh has I tried using body.current.position, in useFrame, but the vector coordinates of the position don't update when I move around. I also tried using body.current.translation() but there was an error
I have a very simple grid based game that uses ecctrl
. Sadly my (vite) builds don't work as tsc
always errors on ecctrl (even with skipLibCheck: true
).
This is my code:
import { RigidBody } from "@react-three/rapier";
import Ecctrl from "ecctrl";
import Bear from "./components/Bear";
import { mainMap } from "./lib/maps";
import { models } from "./lib/models";
export default function Experience() {
return (
<>
<ambientLight intensity={2} />
<directionalLight position={[-10, 10, 0]} intensity={1} />
<directionalLight position={[10, 10, 0]} intensity={1} />
{/* @ts-expect-error Ecctrl */}
<Ecctrl floatHeight={0}>
<Bear position-y={-0.5} scale={[0.7, 0.7, 0.7]} />
</Ecctrl>
<RigidBody type="fixed" colliders="trimesh" scale={[8, 8, 8]}>
{mainMap.map((rows, rowIndex) =>
rows.map((model, colIndex) => {
return models[model]({ position: [colIndex, 0, rowIndex] });
}),
)}
</RigidBody>
</>
);
}
Am I doing something wrong?
Here is the error log when trying to build:
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:82:9 - error TS6133: 'jumpLandAnimation' is declared but its value is never read.
82 const jumpLandAnimation = !animated
~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:357:7 - error TS2322: Type 'null' is not assignable to type 'DirectionalLight'.
357 let dirLight: THREE.DirectionalLight = null;
~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:371:18 - error TS6133: 'followCam' is declared but its value is never read.
371 const { pivot, followCam, cameraCollisionDetect } =
~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:396:7 - error TS2322: Type 'null' is not assignable to type 'RayColliderToi'.
396 let rayHit: RayColliderToi = null;
~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:404:7 - error TS2322: Type 'null' is not assignable to type 'number'.
404 let slopeAngle: number = null;
~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:405:7 - error TS2322: Type 'null' is not assignable to type 'Vector'.
405 let actualSlopeNormal: Vector = null;
~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:406:7 - error TS2322: Type 'null' is not assignable to type 'number'.
406 let actualSlopeAngle: number = null;
~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:412:7 - error TS2322: Type 'null' is not assignable to type 'RayColliderToi'.
412 let slopeRayHit: RayColliderToi = null;
~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:444:37 - error TS18048: 'characterModelRef.current' is possibly 'undefined'.
444 movingDirection.applyQuaternion(characterModelRef.current.quaternion);
~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:492:7 - error TS18048: 'characterRef.current' is possibly 'undefined'.
492 characterRef.current.mass()
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:499:16 - error TS18048: 'characterModelRef.current' is possibly 'undefined'.
499 Math.sin(characterModelRef.current.rotation.y).toFixed(3) ==
~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:537:5 - error TS18048: 'characterRef.current' is possibly 'undefined'.
537 characterRef.current.applyImpulseAtPoint(
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:553:29 - error TS18048: 'characterRef.current' is possibly 'undefined'.
553 -autoBalanceSpringK * characterRef.current.rotation().x -
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:554:7 - error TS18048: 'characterRef.current' is possibly 'undefined'.
554 characterRef.current.angvel().x * autoBalanceDampingC,
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:555:29 - error TS18048: 'characterRef.current' is possibly 'undefined'.
555 -autoBalanceSpringK * characterRef.current.rotation().y -
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:556:7 - error TS18048: 'characterRef.current' is possibly 'undefined'.
556 characterRef.current.angvel().y * autoBalanceDampingOnY,
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:557:29 - error TS18048: 'characterRef.current' is possibly 'undefined'.
557 -autoBalanceSpringK * characterRef.current.rotation().z -
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:558:7 - error TS18048: 'characterRef.current' is possibly 'undefined'.
558 characterRef.current.angvel().z * autoBalanceDampingC
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:560:5 - error TS18048: 'characterRef.current' is possibly 'undefined'.
560 characterRef.current.applyTorqueImpulse(dragAngForce, false);
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:566:18 - error TS18048: 'characterModelRef.current' is possibly 'undefined'.
566 dirLight = characterModelRef.current.parent.parent.children.find(
~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:566:18 - error TS18047: 'characterModelRef.current.parent' is possibly 'null'.
566 dirLight = characterModelRef.current.parent.parent.children.find(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:566:18 - error TS18047: 'characterModelRef.current.parent.parent' is possibly 'null'.
566 dirLight = characterModelRef.current.parent.parent.children.find(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:578:23 - error TS2721: Cannot invoke an object which is possibly 'null'.
578 animated && action1Animation();
~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:588:23 - error TS2721: Cannot invoke an object which is possibly 'null'.
588 animated && action2Animation();
~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:598:23 - error TS2721: Cannot invoke an object which is possibly 'null'.
598 animated && action3Animation();
~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:608:23 - error TS2721: Cannot invoke an object which is possibly 'null'.
608 animated && action4Animation();
~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:623:5 - error TS18048: 'characterRef.current' is possibly 'undefined'.
623 characterRef.current.setEnabledRotations(
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:644:7 - error TS2322: Type 'Group<Object3DEventMap> | undefined' is not assignable to type 'Object3D<Object3DEventMap>'.
Type 'undefined' is not assignable to type 'Object3D<Object3DEventMap>'.
644 dirLight.target = characterModelRef.current;
~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:698:7 - error TS18048: 'characterRef.current' is possibly 'undefined'.
698 characterRef.current.setLinvel(
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:714:5 - error TS18048: 'characterModelRef.current' is possibly 'undefined'.
714 characterModelRef.current.quaternion.rotateTowards(
~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:734:5 - error TS2322: Type 'RayColliderToi | null' is not assignable to type 'RayColliderToi'.
Type 'null' is not assignable to type 'RayColliderToi'.
734 rayHit = world.castRay(
~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:738:7 - error TS2345: Argument of type 'null' is not assignable to parameter of type 'QueryFilterFlags | undefined'.
738 null,
~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:776:38 - error TS2531: Object is possibly 'null'.
776 const rayHitObjectBodyType = rayHit.collider.parent().bodyType();
~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:777:38 - error TS2531: Object is possibly 'null'.
777 const rayHitObjectBodyMass = rayHit.collider.parent().mass();
~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:789:18 - error TS2531: Object is possibly 'null'.
789 .sub(rayHit.collider.parent().translation() as THREE.Vector3);
~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:791:38 - error TS2531: Object is possibly 'null'.
791 const movingObjectLinvel = rayHit.collider
~~~~~~~~~~~~~~~
792 .parent()
~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:795:38 - error TS2531: Object is possibly 'null'.
795 const movingObjectAngvel = rayHit.collider
~~~~~~~~~~~~~~~
796 .parent()
~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:825:13 - error TS2531: Object is possibly 'null'.
825 rayHit.collider
~~~~~~~~~~~~~~~
826 .parent()
~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:843:5 - error TS18048: 'slopeRayOriginRef.current' is possibly 'undefined'.
843 slopeRayOriginRef.current.getWorldPosition(slopeRayorigin);
~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:845:5 - error TS2322: Type 'RayColliderToi | null' is not assignable to type 'RayColliderToi'.
Type 'null' is not assignable to type 'RayColliderToi'.
845 slopeRayHit = world.castRay(
~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:849:7 - error TS2345: Argument of type 'null' is not assignable to parameter of type 'QueryFilterFlags | undefined'.
849 null,
~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:857:7 - error TS2322: Type 'Vector | undefined' is not assignable to type 'Vector'.
Type 'undefined' is not assignable to type 'Vector'.
857 actualSlopeNormal = slopeRayHit.collider.castRayAndGetNormal(
~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:880:9 - error TS2322: Type 'null' is not assignable to type 'number'.
880 slopeAngle = null;
~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:883:7 - error TS2322: Type 'null' is not assignable to type 'number'.
883 slopeAngle = null;
~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:893:11 - error TS18048: 'characterRef.current' is possibly 'undefined'.
893 characterRef.current.linvel().y * dampingC;
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:894:9 - error TS18048: 'characterRef.current' is possibly 'undefined'.
894 characterRef.current.applyImpulse(
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:918:9 - error TS18048: 'characterRef.current' is possibly 'undefined'.
918 characterRef.current.applyImpulse(dragForce, false);
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:927:9 - error TS18048: 'characterRef.current' is possibly 'undefined'.
927 characterRef.current.applyImpulse(dragForce, false);
~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:955:9 - error TS2721: Cannot invoke an object which is possibly 'null'.
955 idleAnimation();
~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:957:9 - error TS2721: Cannot invoke an object which is possibly 'null'.
957 jumpAnimation();
~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:959:15 - error TS2721: Cannot invoke an object which is possibly 'null'.
959 run ? runAnimation() : walkAnimation();
~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:959:32 - error TS2721: Cannot invoke an object which is possibly 'null'.
959 run ? runAnimation() : walkAnimation();
~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:961:9 - error TS2721: Cannot invoke an object which is possibly 'null'.
961 jumpIdleAnimation();
~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:965:9 - error TS2721: Cannot invoke an object which is possibly 'null'.
965 fallAnimation();
~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:977:7 - error TS2322: Type 'MutableRefObject<RigidBody | undefined>' is not assignable to type 'Ref<RigidBody> | undefined'.
Type 'MutableRefObject<RigidBody | undefined>' is not assignable to type 'RefObject<RigidBody>'.
Types of property 'current' are incompatible.
Type 'RigidBody | undefined' is not assignable to type 'RigidBody | null'.
Type 'undefined' is not assignable to type 'RigidBody | null'.
977 ref={characterRef}
~~~
node_modules/.pnpm/@[email protected]/node_modules/@types/react/index.d.ts:151:9
151 ref?: Ref<T> | undefined;
~~~
The expected type comes from property 'ref' which is declared here on type 'IntrinsicAttributes & RigidBodyProps & RefAttributes<RigidBody>'
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:980:14 - error TS2322: Type 'MutableRefObject<Group<Object3DEventMap> | undefined>' is not assignable to type 'Ref<Group<Object3DEventMap>> | undefined'.
Type 'MutableRefObject<Group<Object3DEventMap> | undefined>' is not assignable to type 'RefObject<Group<Object3DEventMap>>'.
Types of property 'current' are incompatible.
Type 'Group<Object3DEventMap> | undefined' is not assignable to type 'Group<Object3DEventMap> | null'.
Type 'undefined' is not assignable to type 'Group<Object3DEventMap> | null'.
980 <group ref={characterModelRef} userData={{ camExcludeCollision: true }}>
~~~
node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@react-three/fiber/dist/declarations/src/three-types.d.ts:27:5
27 ref?: React.Ref<T>;
~~~
The expected type comes from property 'ref' which is declared here on type 'GroupProps'
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/Ecctrl.tsx:988:11 - error TS2322: Type 'MutableRefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | undefined>' is not assignable to type 'Ref<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>> | undefined'.
Type 'MutableRefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | undefined>' is not assignable to type 'RefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>>'.
Types of property 'current' are incompatible.
Type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | undefined' is not assignable to type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | null'.
Type 'undefined' is not assignable to type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | null'.
988 ref={slopeRayOriginRef}
~~~
node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@react-three/fiber/dist/declarations/src/three-types.d.ts:27:5
27 ref?: React.Ref<T>;
~~~
The expected type comes from property 'ref' which is declared here on type 'MeshProps'
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:5:27 - error TS2307: Cannot find module 'three/examples/jsm/loaders/GLTFLoader' or its corresponding type declarations.
5 import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:41:7 - error TS18047: 'action' is possibly 'null'.
41 action
~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:44:34 - error TS2352: Conversion of type 'undefined' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
44 .setLoop(THREE.LoopOnce, undefined as number)
~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:46:7 - error TS18047: 'action' is possibly 'null'.
46 action.clampWhenFinished = true;
~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:48:7 - error TS18047: 'action' is possibly 'null'.
48 action.reset().fadeIn(0.2).play();
~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:56:7 - error TS18047: 'action' is possibly 'null'.
56 action.fadeOut(0.2);
~~~~~~
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/EcctrlAnimation.tsx:68:14 - error TS2322: Type 'MutableRefObject<undefined>' is not assignable to type 'Ref<Group<Object3DEventMap>> | undefined'.
Type 'MutableRefObject<undefined>' is not assignable to type 'RefObject<Group<Object3DEventMap>>'.
Types of property 'current' are incompatible.
Type 'undefined' is not assignable to type 'Group<Object3DEventMap> | null'.
68 <group ref={group} dispose={null} userData={{ camExcludeCollision: true }}>
~~~
node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@react-three/fiber/dist/declarations/src/three-types.d.ts:27:5
27 ref?: React.Ref<T>;
~~~
The expected type comes from property 'ref' which is declared here on type 'GroupProps'
node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@[email protected]_@types+t_4ggvehjjhyu3gmh3ukftw5ie7m/node_modules/ecctrl/src/stores/useGame.ts:11:21 - error TS2352: Conversion of type 'null' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
11 curAnimation: null as string,
~~~~~~~~~~~~~~
I can get a ref to the ecctrl to get the player .translation()
but is there a way to get rotation too?
I need it to determine the direction of a thrown object from the player.
Thanks.
Would be nice if it won't only relay on keyboard, but also on mobile touch controls is there is a way to do this?
Do you have any hints How can I integrate with @react-three/xr ? I would like to use it as it works by default with additional support of VR, when when enter VR is clicked. Any hints are welcome.
Could you please explain the value range of setJoystick(joystickDis, joystickAng, runState) parameter? When I force the canvas to landscape, the gesture slide is perpendicular to the character movement direction, so I need to customize Joystick
Hi, Erdong Chen.
Could you increase the animation amount for customizing?
Current, In your module, has the 1โ10 animations.
But, I want to use at least 1โ20 animations.
Thanks for your project.
Ecctrl is taking the default camera using const { scene, camera } = useThree();
This means if we add another camera and mark it as the default camera Ecctrl will immediately take control of the camera.
But there are a use case where you want to cut to a different camera (let's say a flying map overview) and go back to the player's camera. So basically you want your new camera not to be controlled by ecctrl.
Therefore I would like to introduce a prop like camFollow: boolean
then in Ecctrl.tsx
line 989 we could do something like this:
/**
* Camera movement
*/
if(camFollow) {
pivotPosition.set(
currentPos.x + camTargetPos.x,
currentPos.y + (camTargetPos.y || (capsuleHalfHeight + capsuleRadius / 2)),
currentPos.z + camTargetPos.z
);
pivot.position.lerp(pivotPosition, 1 - Math.exp(-camFollowMult * delta));
state.camera.lookAt(pivot.position);
}
and in useFollowCam.tsx
we skip the mouse / touch events:
// Mouse move event
const onDocumentMouseMove = (e: MouseEvent) => {
if(!camFollow) return false;
...
// Mouse scroll event
const onDocumentMouseWheel = (e: Event) => {
if(!camFollow) return false;
...
// Touch move event
const onTouchMove = (e: TouchEvent) => {
// prevent swipe to navigate gesture
e.preventDefault();
e.stopImmediatePropagation();
if(!camFollow) return false;
That would help us cutting to different camera view when needed.
If you think it's a good idea I can create a pull request!
I want to use TransformControls to automatically disable the built-in controller.
But I couldn't find the corresponding parameter to control it.
If using disableFollowCam
, the camera position will suddenly change.
Hey! I noticed that the component doesn't seem to work like its supposed to when using Ecctrl. The sound volume from the Positional Audio are the same no matter how far away the character/camera is.
Hi,
I have quite a high poly count at the moment and it seems to upset the engine.
If there is too much, the character starts to spin wildly out of control.
Isn't there some way to stabilise the character and why is this happening?
Thanks.
Hi,
I'm a newbie.
I'm currently learning by doing some game experiment with react-three-fiber.
I want to get the current position of the character which is being controlled by the ecctrl, how can i get it
I tried a simple way by wrapping it inside a component and test it by logging the position but it still always the same position, although the character is moved:
const ControlledCharacter = () => {
const charRef = useRef();
window.onkeydown = (e) => {
console.log(charRef.current);
console.log(charRef.current.position); // always the same position, although the character is moved
};
return (
<group ref={charRef}>
<Ecctrl
// debug
animated
floatHeight={0}
followLight
springK={2}
dampingC={0.2}
autoBalanceSpringK={1.2}
autoBalanceDampingC={0.04}
autoBalanceSpringOnY={0.7}
>
<EcctrlAnimation
characterURL={characterURL}
animationSet={animationSet}
>
<Demon position={[0, -0.65, 0]} />
</EcctrlAnimation>
</Ecctrl>
</group>
);
};
Am I doing something wrong? If so, is there any way to get the current position of the model? Thank you very much for your assistance and guidance.
on line 29 of EcctrlAnimation.tsx is this code which I think is trying to set actions[props.animationsSet.jumpIdle] but jumpIdle is optional, so the code fails if you've removed it
29: const action =
actions[curAnimation ? curAnimation : props.animationSet.jumpIdle];
For now the solution for the user is to always specify jumpIdle in the animation set.
I am getting the following error when redirecting on a page.
Uncaught Error: null pointer passed to rust
I created a code sandbox here: https://codesandbox.io/p/sandbox/jovial-tdd-njw3j3
Here, when clicking on the tree I implemented a redirect. You will see the error as well in the Browser Dev Tools (not the built-in Dev Tools of Codesandbox, even though it will probably show there as well)
Here's some more of the error message:
The above error occurred in the <ForwardRef> component: at eval (webpack-internal:///(app-pages-browser)/./node_modules/ecctrl/dist/Ecctrl.js:1093:11) at KeyboardControls (webpack-internal:///(app-pages-browser)/./node_modules/@react-three/drei/web/KeyboardControls.js:19:11) at Physics (webpack-internal:///(app-pages-browser)/./node_modules/@react-three/rapier/dist/react-three-rapier.esm.js:747:13) at Suspense at Suspense at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/@react-three/fiber/dist/index-8afac004.esm.js:441:9) at FiberProvider (webpack-internal:///(app-pages-browser)/./node_modules/its-fine/dist/index.js:66:1) at Provider (webpack-internal:///(app-pages-browser)/./node_modules/@react-three/fiber/dist/index-8afac004.esm.js:1982:11)
Any idea how to prevent this error?
For example, in context of a parkour game, when character falls off the ground, it would be nice for the parent of Ecctrl to capture the character's state (like its height) for game logic, and drive Ecctrl to reset character's position (otherwise it will be falling forever)
(Great project BTW!)
Hello! Personally, I'm encountering an error when deploying an application using this package.
Has anyone else tried deploying it, or could the error be on my end? (I'm using Vercel personally)
Here's the specific error:
TypeError: object null is not iterable (cannot read property Symbol(Symbol.iterator))
I'm using Vite and React latest versions
I can control the movement of the character, but I don't know how to change the position of the camera, and use the mouse to control the camera to rotate around the objec
I have a custom character model (who will have animations at a later date)
I visualise the cuboid with a Box.
I add the CuboidCollider inside Ecctrl.
The player finds the floor very bouncy and flies into the sky.
<Ecctrl debug ref={ecctrlRef} autoBalance={false} animated position={pos} jumpVel={0}>
{/* <EcctrlAnimation characterURL={characterURL} animationSet={animationSet}> */}
<CuboidCollider args={[1,2.15,1]} mass={0} position={[0,0.5,0]}/>
<Box args={[1,2.15,1]} position={[0,0.5,0]} />
<BaseMale scale={0.8} position={[0,-0.9,0]}/>
{/* </EcctrlAnimation> */}
</Ecctrl>
Hiya!
I'm glad to see this package. Been trying to implement it well for a long time :D
I'm running into some issues interacting with other RigidBodies and sensor-Colliders.
Here it's floating on top of the sensors. When running into one it can either bounce me up, work without any problems or just make the character stuck.
Tabbing out and tabbing in sometimes solves this issue.
Happy to help debugging this, just flagging it.
I want to set the followCam position a little higher on the y-axis, but i have no idea how to do it. i've played with the camInitDis property but still not ideal.
After I use the ecctrl to create a character, I want to add some noise to the environment, but I found that the "PositionalAudio" component is not working properly! Do you have any suggestions to help with this issue?
My character can't jump. This is my Ground code. Please help!
import { Plane } from "@react-three/drei";
import { RapierRigidBody, RigidBody } from "@react-three/rapier";
import { useRef } from "react";
const Ground = () => {
const ref = useRef(null);
return (
<Plane
position={[0, 0, 0]}
args={[1000, 1000]}
rotation={[-Math.PI / 2, 0, 0]}
>
);
};
Hello!
While working on my project which uses Ecctrl I found two things with which I spent a lot of time to figure it out.
Please, if it's possible, add those to the documentation or create some FAQ:
Filling these animations is essential (otherwise you'll encounter errors, you can't have animations for example for only idle and walk):
const animationSet = {
idle: "yourAnimationName",
walk: "yourAnimationName",
run: "yourAnimationName",
jump: "yourAnimationName",
jumpIdle: "yourAnimationName",
jumpLand: "yourAnimationName",
fall: "yourAnimationName",
}
If you will fill different properties of animationSet with same name of animations, those animations will play only once.
In my case:
const animationSet = {
idle: 'Idle_Armature',
walk: 'Walk_Armature',
run: 'Falling_Armature',
jump:'Falling_Armature',
jumpIdle: 'Falling_Armature',
jumpLand: 'Idle_Armature',
fall: 'Falling_Armature',
action1: 'Falling_Armature',
action2: 'Falling_Armature',
action3: 'Falling_Armature',
action4: 'Falling_Armature',
}
idleAnimation, when character is doing nothing, will play only once and then character will not play any animation, just freeze on first/last frame of the animation played.
Hello,
Thanks a lot for this great project, I am sure it will have a big impact in the future of web 3D.
Do you plan to upgrade the character control to any type of colliders ? I mean for the moment it works for floating capsule but what about a car ? That is just an example. Maybe it is already possible to convert the capsule to other collider but I didn't find a way to do it.
Have a great day !
When setting my idle
animation, I was expecting it to loop like the walk
, but instead it gets played only once, after the character stays static.
Thank you for your amazing job ๐
My setup is usually so that I have a character.glb file and then lots of different animations from one or multiple fbx files, which I apply on the character like this:
(this setup makes totally sense when you have multiple characters in a multiplayer game with small size and have only once to load all the animations for all players (since they are all the same right?):
const {scene}= useGLTF("character.glb");
const walkingFbx = useFBX("walking.fbx");
const { actions } = useAnimations(walkingFbx.animations, characterRef);
useEffect(() => {
actions?.[Object.keys(actions)[0]]?.play();
}, [actions]);
//..
<primitive ref={characterRef} object={scene} />
how would I achieve this in this case:
/**
* Character url preset
*/
const characterURL = './Demon.glb'
/**
* Character animation set preset
*/
const animationSet = {
idle: 'CharacterArmature|Idle',
walk: 'CharacterArmature|Walk',
run: 'CharacterArmature|Run',
jump: 'CharacterArmature|Jump',
jumpIdle: 'CharacterArmature|Jump_Idle',
jumpLand: 'CharacterArmature|Jump_Land',
fall: 'CharacterArmature|Duck', // This is for falling from high sky
action1: 'CharacterArmature|Wave',
action2: 'CharacterArmature|Death',
action3: 'CharacterArmature|HitReact',
action4: 'CharacterArmature|Punch'
}
//...
<EcctrlAnimation characterURL={characterURL} animationSet={animationSet}>
<CharacterModel />
</EcctrlAnimation>
Do I need to manipulte the EcctrlAnimation.tsx by myself?
export function EcctrlAnimation(props: EcctrlAnimationProps) {
// Change the character src to yours
const group = useRef();
const animations= useFBX("allmyAnimationsIn1FBX.fbx"); //here?
const { actions } = useAnimations(animations, group);
`
import { Canvas, useFrame } from '@react-three/fiber'
import { Environment, KeyboardControls, OrbitControls } from "@react-three/drei"
import { Perf } from 'r3f-perf';
import './App.css'
import Light from './Components/Light'
import { Map } from './Components/Map'
import { Map2 } from './Components/Map2'
import { Map4 } from './Components/Map4'
import { Map3 } from './Components/Map3'
// import { Map } from './Components/Map'
import { Physics, RigidBody } from '@react-three/rapier'
import { Suspense, useEffect, useRef } from 'react';
import { AnimaCharacterModel } from './Components/AnimaCharacterModel';
import { Avatar } from './Components/Avatar';
import Ecctrl, { EcctrlAnimation, EcctrlJoystick } from 'ecctrl';
import { useConfigurator } from './contexts/Configurator';
function App() {
const { loading, setLoading } = useConfigurator();
const keyboardMap = [
{ name: 'forward', keys: ['ArrowUp', 'KeyW'] },
{ name: 'backward', keys: ['ArrowDown', 'KeyS'] },
{ name: 'leftward', keys: ['ArrowLeft', 'KeyA'] },
{ name: 'rightward', keys: ['ArrowRight', 'KeyD'] },
{ name: 'jump', keys: ['Space'] },
{ name: 'run', keys: ['Shift'] },
{ name: 'action1', keys: ['1'] },
{ name: 'action2', keys: ['2'] },
{ name: 'action3', keys: ['3'] },
{ name: 'action4', keys: ['KeyF'] }
]
const characterURL = './AnimatedWoman.glb';
const animationSet = {
idle: 'CharacterArmature|Idle',
walk: 'CharacterArmature|Walk',
run: 'CharacterArmature|Run',
jump: 'CharacterArmature|Idle',
jumpIdle: 'CharacterArmature|Idle',
jumpLand: 'CharacterArmature|Idle',
fall: 'CharacterArmature|Idle', // This is for falling from high sky
action1: 'CharacterArmature|Wave',
action2: 'CharacterArmature|Death',
action3: 'CharacterArmature|HitRecieve',
action4: 'CharacterArmature|Punch_Left'
}
return (
<>
{/* */}
<Physics timeStep={"vary"} >
<Suspense fallback={null}>
{loading === true && (
<Ecctrl animated position={[0, 10, 0]} >
<EcctrlAnimation characterURL={characterURL}
animationSet={animationSet}>
<Avatar />
</EcctrlAnimation>
</Ecctrl>
)}
</Suspense>
</KeyboardControls>
<RigidBody type="fixed" name="ground">
<mesh position-y={-5.3} receiveShadow>
<boxGeometry args={[50, 0.5, 50]} />
<meshStandardMaterial color="mediumpurple" />
</mesh>
</RigidBody>
{/* <Map4 /> */}
{/* <Map2 /> */}
<Map4 />
</Physics>
<OrbitControls />
</Canvas>
</>
)
}
export default App
`
Map4 here
`import React, { useEffect, useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { useConfigurator } from '../contexts/Configurator';
import { GLTFLoader } from 'three-stdlib';
import { RigidBody } from '@react-three/rapier';
export function Map4(props) {
const { nodes, materials } = useGLTF('/metafactory_booth.glb')
const loader = new GLTFLoader();
const { loading, setLoading } = useConfigurator();
useEffect(()=>{
loader.load(
"/metafactory_booth.glb",
( gltf ) => {
setLoading(true)
},
( xhr ) => {
// called while loading is progressing
console.log( `${( xhr.loaded / xhr.total * 100 )}% loaded` );
},
( error ) => {
// called when loading has errors
console.error( 'An error happened', error );
},
);
});
return (
<group {...props} dispose={null} position={[0,-3,0]}>
<group name="Clothes_rack_8" position={[0, 1.827, 0]} rotation={[-Math.PI / 2, 0, 0]} scale={0.024}>
<group name="Object_6_7" position={[-23.032, 260.432, -5.813]} rotation={[0, 0, -3.133]} scale={0.604}>
<group name="B1_Teal_9" position={[3.29, 7.184, 5.46]} rotation={[0, -1.54, 0]} scale={[0.822, 0.822, 0.009]}>
<group name="Sketchfab_model_14" position={[16.228, 0, 0]} rotation={[-Math.PI / 2, 0, 0]} scale={0.526}>
<mesh name="Object_27" geometry={nodes.Object_27.geometry} material={materials['Materiale.002']} position={[-30.794, -0.149, 2.86]} scale={[0.698, 0.928, 0.695]} />
<mesh name="Object_29" geometry={nodes.Object_29.geometry} material={materials.aiStandard2SG} position={[3.799, 0, 0]} scale={[1.735, 1, 1]} />
<group name="B1_Teal001_15" position={[-0.666, 2.041, 4.385]} rotation={[-Math.PI, 0, -Math.PI]} scale={[0.211, 0.211, 0.002]}>
<group name="Cube001_26" position={[-2.906, 1.746, -3.9]} rotation={[0, Math.PI / 2, 0]} scale={[0.445, 0.325, 0.877]}>
<mesh name="Object_57" geometry={nodes.Object_57.geometry} material={materials['Materiale.004']} />
<group name="Cube002_30" position={[-2.91, 1.746, -5.816]} rotation={[0, Math.PI / 2, 0]} scale={[0.445, 0.325, 0.877]}>
<mesh name="Object_60" geometry={nodes.Object_60.geometry} material={materials['Materiale.004']} />
<group name="Cube003_31" position={[1.839, 1.746, -5.816]} rotation={[0, Math.PI / 2, 0]} scale={[0.445, 0.325, 0.877]}>
<mesh name="Object_63" geometry={nodes.Object_63.geometry} material={materials['Materiale.004']} />
{/* <mesh name="Object_7_1" geometry={nodes.Object_7_1.geometry} material={materials.Materiale} rotation={[-Math.PI / 2, 0, 0]} /> */}
<mesh name="Object_11" geometry={nodes.Object_11.geometry} material={materials.boothsheet_branding} rotation={[-Math.PI / 2, 0, 0]} />
<mesh name="Object_23" geometry={nodes.Object_23.geometry} material={materials['tshirt.003']} position={[-2.483, 2.37, -4.051]} scale={0.782} />
<mesh name="Object_36" geometry={nodes.Object_36.geometry} material={materials.material} position={[2.273, 2.496, -5.983]} rotation={[0.004, -0.32, 0.002]} scale={1.22} />
<mesh name="Object_38" geometry={nodes.Object_38.geometry} material={materials.hoodie} position={[-3.305, 2.479, -5.865]} rotation={[0, 0.096, 0]} />
<mesh name="Object_40" geometry={nodes.Object_40.geometry} material={materials.longsleeve} position={[1.427, 2.204, -5.966]} rotation={[0, -0.014, 0]} scale={1.206} />
<mesh name="Object_42" geometry={nodes.Object_42.geometry} material={materials.Atlas1} position={[1.918, 2.477, 6.525]} rotation={[Math.PI / 2, 0, 0]} scale={0.01} />
<mesh name="Object_44" geometry={nodes.Object_44.geometry} material={materials.material_0} position={[-1.327, 2.54, 4.819]} rotation={[Math.PI / 2, 0, 0]} scale={0.012} />
<mesh name="Object_46" geometry={nodes.Object_46.geometry} material={materials.Jacket} position={[-0.723, 3.126, 4.932]} rotation={[Math.PI / 2, 0, 0]} scale={0.012} />
<mesh name="Object_48" geometry={nodes.Object_48.geometry} material={materials.Materiale} position={[-0.685, 3.372, 4.791]} rotation={[Math.PI / 2, 0, 0]} scale={0.012} />
<mesh name="Object_50" geometry={nodes.Object_50.geometry} material={materials.tanktop} position={[-3.366, 2.367, -4.047]} rotation={[-Math.PI, -0.015, -Math.PI]} />
<mesh name="Object_52" geometry={nodes.Object_52.geometry} material={materials.sneakers} position={[-2.303, 2.065, -5.932]} rotation={[-Math.PI, 0.515, -Math.PI]} />
<mesh name="Object_54" geometry={nodes.Object_54.geometry} material={materials.Material} position={[2.28, 2.31, -5.987]} rotation={[0, 1.54, 0]} />
<mesh name="Object_65" geometry={nodes.Object_65.geometry} material={materials['Materiale.003']} position={[-2.9, 1.599, -3.896]} scale={[0.957, 0.006, 0.529]} />
<mesh name="Object_67" geometry={nodes.Object_67.geometry} material={materials['Materiale.003']} position={[-2.9, 1.599, -5.808]} scale={[0.957, 0.006, 0.529]} />
<mesh name="Object_69" geometry={nodes.Object_69.geometry} material={materials['Materiale.003']} position={[1.836, 1.599, -5.808]} scale={[0.957, 0.006, 0.529]} />
<mesh name="Object_71" geometry={nodes.Object_71.geometry} material={materials['Materiale.003']} position={[-0.672, 1.599, 4.86]} scale={[2.546, 0.006, 0.529]} />
)
}
useGLTF.preload('/metafactory_booth.glb')`
Again, thanks so much for making this character control available. It's so helpful!
However, another issue I am having is that I cannot get the animations & controls to behave correctly.
When walking with the character, the animations are not getting triggered correctly. Also I can walk or run with the character, but the Jump control is not working when hitting the spacebar
Here is a codesandbox showing the issue: https://codesandbox.io/p/sandbox/test-ecctrl-mqc2t6
Appreciate any feedback!
I recently deleted the 'node_modules' folder and reinstalled the project. However, only the 'ecctrl' library is unable to find TypeScript type declarations. Below is my 'package.json' file. I hope to receive help and welcome any suggestions.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.