-
-
Notifications
You must be signed in to change notification settings - Fork 397
Support collision group and fix the position of characterController synchronization late issue #2614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support collision group and fix the position of characterController synchronization late issue #2614
Changes from 11 commits
0e1cc65
f9df061
2c53eef
fc9e0ac
5291a5f
092f26f
6b06408
c0c6faf
9cde2f7
2d6e210
9156ff2
f190cb6
fa46851
84b5030
c71e392
8fcfcff
6347462
f899d28
afd8f2c
f04ed3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| /** | ||
| * @title LitePhysics Collision Group | ||
| * @category Physics | ||
| */ | ||
| import { | ||
| WebGLEngine, | ||
| SphereColliderShape, | ||
| DynamicCollider, | ||
| BoxColliderShape, | ||
| Vector3, | ||
| MeshRenderer, | ||
| PointLight, | ||
| PrimitiveMesh, | ||
| Camera, | ||
| Script, | ||
| StaticCollider, | ||
| ColliderShape, | ||
| PBRMaterial, | ||
| Entity, | ||
| Layer | ||
| } from "@galacean/engine"; | ||
|
|
||
| import { LitePhysics } from "@galacean/engine-physics-lite"; | ||
| import { initScreenshot, updateForE2E } from "./.mockForE2E"; | ||
| class MoveScript extends Script { | ||
| onUpdate() { | ||
| this.entity.transform.position.y -= 0.1; | ||
| } | ||
|
|
||
| onTriggerEnter(other: ColliderShape) { | ||
| // Change color to green when collision occurs | ||
| (this.entity.getComponent(MeshRenderer).getMaterial() as PBRMaterial).baseColor.set(0, 1, 0, 1); | ||
| } | ||
| } | ||
| // Create a sphere with physics | ||
| function createPhysicsSphere( | ||
| rootEntity: Entity, | ||
| name: string, | ||
| position: Vector3, | ||
| radius: number, | ||
| color: Vector3, | ||
| collisionGroup: number | ||
| ) { | ||
| const sphereEntity = rootEntity.createChild(name); | ||
| sphereEntity.transform.setPosition(position.x, position.y, position.z); | ||
| sphereEntity.addComponent(MoveScript); | ||
|
|
||
| // Add visual representation | ||
| const sphereMtl = new PBRMaterial(rootEntity.engine); | ||
| const sphereRenderer = sphereEntity.addComponent(MeshRenderer); | ||
| sphereMtl.baseColor.set(color.x, color.y, color.z, 1.0); | ||
| sphereMtl.metallic = 0.0; | ||
| sphereMtl.roughness = 0.5; | ||
| sphereRenderer.mesh = PrimitiveMesh.createSphere(rootEntity.engine, radius); | ||
| sphereRenderer.setMaterial(sphereMtl); | ||
|
|
||
| // Add physics | ||
| const physicsSphere = new SphereColliderShape(); | ||
| physicsSphere.radius = radius; | ||
|
|
||
| const sphereCollider = sphereEntity.addComponent(DynamicCollider); | ||
| sphereCollider.collisionGroup = collisionGroup; | ||
| sphereCollider.addShape(physicsSphere); | ||
|
|
||
| return sphereEntity; | ||
| } | ||
|
|
||
| WebGLEngine.create({ canvas: "canvas", physics: new LitePhysics() }).then((engine) => { | ||
| engine.canvas.resizeByClientSize(); | ||
| const scene = engine.sceneManager.activeScene; | ||
| const rootEntity = scene.createRootEntity("root"); | ||
|
|
||
| // Set up ambient lighting | ||
| scene.ambientLight.diffuseSolidColor.set(1, 1, 1, 1); | ||
| scene.ambientLight.diffuseIntensity = 1.2; | ||
|
|
||
| // Set up camera | ||
| const cameraEntity = rootEntity.createChild("camera"); | ||
| const camera = cameraEntity.addComponent(Camera); | ||
| cameraEntity.transform.setPosition(0, 3, 15); | ||
| cameraEntity.transform.lookAt(new Vector3(0, 0, 0)); | ||
|
|
||
| // Add point light | ||
| const light = rootEntity.createChild("light"); | ||
| light.transform.setPosition(0, 10, 0); | ||
| const pointLight = light.addComponent(PointLight); | ||
| pointLight.intensity = 1.5; | ||
|
|
||
| const groundEntity = rootEntity.createChild("ground"); | ||
|
|
||
| // 设置立方体的位置和大小 | ||
| groundEntity.transform.setPosition(0, 1, 0); | ||
| // groundEntity.isActive = false; | ||
|
|
||
| // Visual representation of the ground cube | ||
| const groundMtl = new PBRMaterial(engine); | ||
| groundMtl.baseColor.set(0.5, 0.5, 0.5, 1.0); | ||
| groundMtl.roughness = 0.7; | ||
|
|
||
| const cubeSize = new Vector3(10, 0.2, 10); | ||
| const groundRenderer = groundEntity.addComponent(MeshRenderer); | ||
| groundRenderer.mesh = PrimitiveMesh.createCuboid(engine, cubeSize.x, cubeSize.y, cubeSize.z); | ||
| groundRenderer.setMaterial(groundMtl); | ||
|
|
||
| // Physics for the ground cube | ||
| const groundCollider = groundEntity.addComponent(StaticCollider); | ||
| const groundShape = new BoxColliderShape(); | ||
| groundShape.size = cubeSize; | ||
| groundCollider.addShape(groundShape); | ||
|
|
||
| groundCollider.collisionGroup = 3; | ||
|
|
||
| const sphere1 = createPhysicsSphere(rootEntity, "RedSphere", new Vector3(-2, 5, 0), 0.5, new Vector3(1, 0, 0), 1); | ||
|
|
||
| const sphere2 = createPhysicsSphere(rootEntity, "BlueSphere", new Vector3(2, 5, 0), 0.5, new Vector3(0, 0, 1), 2); | ||
|
|
||
| scene.physics.setColliderGroupCollision(2, 3, false); | ||
| updateForE2E(engine, 1000, 38); | ||
| initScreenshot(engine, camera); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| /** | ||
| * @title Physx Collision Group | ||
| * @category Physics | ||
| */ | ||
| import { | ||
| WebGLEngine, | ||
| SphereColliderShape, | ||
| DynamicCollider, | ||
| BoxColliderShape, | ||
| Vector3, | ||
| MeshRenderer, | ||
| PointLight, | ||
| PrimitiveMesh, | ||
| Camera, | ||
| Script, | ||
| StaticCollider, | ||
| ColliderShape, | ||
| PBRMaterial, | ||
| Entity, | ||
| Layer | ||
| } from "@galacean/engine"; | ||
|
|
||
| import { PhysXPhysics } from "@galacean/engine-physics-physx"; | ||
| import { initScreenshot, updateForE2E } from "./.mockForE2E"; | ||
|
|
||
| class CheckScript extends Script { | ||
| onTriggerEnter(other: ColliderShape) { | ||
| console.log("onTriggerEnter", other); | ||
| // Change color to green when collision occurs | ||
| (this.entity.getComponent(MeshRenderer).getMaterial() as PBRMaterial).baseColor.set(0, 1, 0, 1); | ||
luzhuang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| onContactEnter(other: ColliderShape) { | ||
| console.log("onContactEnter", other); | ||
| // Change color to green when collision occurs | ||
| (this.entity.getComponent(MeshRenderer).getMaterial() as PBRMaterial).baseColor.set(0, 1, 0, 1); | ||
| } | ||
| } | ||
|
|
||
| // Create a sphere with physics | ||
| function createPhysicsSphere( | ||
| rootEntity: Entity, | ||
| name: string, | ||
| position: Vector3, | ||
| radius: number, | ||
| color: Vector3, | ||
| collisionGroup: number | ||
| ) { | ||
| const sphereEntity = rootEntity.createChild(name); | ||
| sphereEntity.transform.setPosition(position.x, position.y, position.z); | ||
|
|
||
| // Add visual representation | ||
| const sphereMtl = new PBRMaterial(rootEntity.engine); | ||
| const sphereRenderer = sphereEntity.addComponent(MeshRenderer); | ||
| sphereMtl.baseColor.set(color.x, color.y, color.z, 1.0); | ||
| sphereMtl.metallic = 0.0; | ||
| sphereMtl.roughness = 0.5; | ||
| sphereRenderer.mesh = PrimitiveMesh.createSphere(rootEntity.engine, radius); | ||
| sphereRenderer.setMaterial(sphereMtl); | ||
|
|
||
| // Add physics | ||
| const physicsSphere = new SphereColliderShape(); | ||
| physicsSphere.radius = radius; | ||
| physicsSphere.material.bounciness = 0.8; | ||
|
|
||
| const sphereCollider = sphereEntity.addComponent(DynamicCollider); | ||
| sphereCollider.collisionGroup = collisionGroup; | ||
| sphereEntity.addComponent(CheckScript); | ||
| sphereCollider.addShape(physicsSphere); | ||
|
|
||
| return sphereEntity; | ||
| } | ||
|
|
||
| WebGLEngine.create({ canvas: "canvas", physics: new PhysXPhysics() }).then((engine) => { | ||
| engine.canvas.resizeByClientSize(); | ||
| const scene = engine.sceneManager.activeScene; | ||
| const rootEntity = scene.createRootEntity("root"); | ||
|
|
||
| // Set up ambient lighting | ||
| scene.ambientLight.diffuseSolidColor.set(1, 1, 1, 1); | ||
| scene.ambientLight.diffuseIntensity = 1.2; | ||
|
|
||
| // Set up camera | ||
| const cameraEntity = rootEntity.createChild("camera"); | ||
| const camera = cameraEntity.addComponent(Camera); | ||
| // 调整相机位置以便更好地观察穿透效果 | ||
| cameraEntity.transform.setPosition(0, 3, 15); | ||
| cameraEntity.transform.lookAt(new Vector3(0, 0, 0)); | ||
|
|
||
| // Add point light | ||
| const light = rootEntity.createChild("light"); | ||
| light.transform.setPosition(0, 10, 0); | ||
| const pointLight = light.addComponent(PointLight); | ||
| pointLight.intensity = 1.5; | ||
|
|
||
| // 创建立方体作为地面 | ||
| const groundEntity = rootEntity.createChild("ground"); | ||
|
|
||
| // 设置立方体的位置和大小 | ||
| groundEntity.transform.setPosition(0, 1, 0); | ||
|
|
||
| // Visual representation of the ground cube | ||
| const groundMtl = new PBRMaterial(engine); | ||
| groundMtl.baseColor.set(0.5, 0.5, 0.5, 1.0); | ||
| groundMtl.roughness = 0.7; | ||
| // 设置半透明以便能看到穿透的球体 | ||
| groundMtl.baseColor.a = 0.5; | ||
|
|
||
| const cubeSize = new Vector3(10, 0.2, 10); | ||
| const groundRenderer = groundEntity.addComponent(MeshRenderer); | ||
| groundRenderer.mesh = PrimitiveMesh.createCuboid(engine, cubeSize.x, cubeSize.y, cubeSize.z); | ||
| groundRenderer.setMaterial(groundMtl); | ||
|
|
||
| // Physics for the ground cube | ||
| const groundCollider = groundEntity.addComponent(StaticCollider); | ||
| const groundShape = new BoxColliderShape(); | ||
| groundShape.size = cubeSize; | ||
| groundCollider.addShape(groundShape); | ||
|
|
||
| groundCollider.collisionGroup = 3; | ||
|
|
||
| // 创建可以碰撞的红色球体 | ||
| const sphere1 = createPhysicsSphere(rootEntity, "RedSphere", new Vector3(-2, 5, 0), 0.5, new Vector3(1, 0, 0), 1); | ||
|
|
||
| // 创建可以穿透的蓝色球体 | ||
| const sphere2 = createPhysicsSphere(rootEntity, "BlueSphere", new Vector3(2, 5, 0), 0.5, new Vector3(0, 0, 1), 2); | ||
|
|
||
| scene.physics.setColliderGroupCollision(2, 3, false); | ||
|
|
||
| updateForE2E(engine, 110); | ||
| initScreenshot(engine, camera); | ||
| }); | ||
luzhuang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -231,6 +231,16 @@ export class PhysicsScene { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Set whether two colliders can collide with each other. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param group1 - The first collision group | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param group2 - The second collision group | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param collide - Whether the colliders should collide | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setColliderGroupCollision(group1: number, group2: number, collide: boolean): void { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GuoLei1990 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PhysicsScene._nativePhysics.setColliderGroupCollision(group1, group2, collide); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
luzhuang marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+250
to
+264
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the bug in the conditional check There's a bug in the validation condition where you check the same variable twice instead of checking both indices. - if (!Number.isInteger(index1) || !Number.isInteger(index1)) {
+ if (!Number.isInteger(index1) || !Number.isInteger(index2)) {
throw new Error("Collision layer must be a single layer (Layer.Layer0 to Layer.Layer31)");
}The condition should check both 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Casts a ray through the Scene and returns the first hit. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param ray - The ray | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.