I“ve got a network scene, with the following GameObjects :
Networking GameObject holding SyncedRoom and Networking components.
PlayerSpawner GameObject holding PlayerSync component whose Asset field has a reference to my prefab Player.
The Player GameObject prefab holds PlayerState, SyncedTransform, Camera and OrbirtControls components.
The Player GameObject prefab has a Sphere as a child which has its normals flipped. Also, this Sphere holds a VideoPlayer component whose VideoClip field has a reference to a 360 video. Both Player GameObject and Sphere have their Transform.position set in (0,0,0)
What Do I want to achieve?
That each Player instances generated by PlayerSync see the interior of the sphere as it was a 360 skybox. That way, I can enable and disable the Sphere for each player.
What“s wrong?
That when an Player instance is generated by PlayerSync, whe I orbit the scene, the sphere also moves with the camera so is like a dizzy effect.
How Can I achieve that for each player, she/he see the interior of the sphere like a 360 skybox and can orbit the scene without moving the sphere?
Hello there ā we have an experimental AI bot that might be able to help you with your question. Would you like to try this out?
How it works:
Reply to the messages of the bot that end with a thread_id to interact with it and ask follow-up questions. You can also mention the bot directly in this channel to get help.
It sounds like you wish to make the sphere behave like a skybox that doesnāt move with the player camera, while still allowing each player instance to enable or disable their own view of the sphere. The sphere should stay in place as the camera orbits around, giving the effect of being inside a static 360° environment.
Hereās an outline of steps in pseudocode on how to achieve that:
Create a Sphere component that doesnāt move with the camera.
Have the Sphere component be instantiated with each player but ensure itās not a child of the Camera GameObject.
Set up the Sphere component so that it is always positioned around the userās camera but doesnāt react to camera rotation or orbit controls.
Provide a method within the PlayerState script to toggle the visibility of the sphere, so each player can enable or disable their own sphere independently.
// Extend the Behaviour class for the Sphere component
export class FixedSkyboxSphere extends Behaviour {
// Store a reference to the VideoPlayer component in the sphere @serializable(Object3D)
private videoPlayerSphere: Object3D;
private cameraPositionCache: Vector3 = new Vector3();
awake() {
// Find and cache the main camera component once during the awake phase
const cameraComponent = this.context.mainCameraComponent;
this.cameraPositionCache.copy(cameraComponent.transform.position);
}
update() {
// On update, set the skybox sphereās position to be centered around the camera
// We update only the position to follow the camera but ignore rotation
this.videoPlayerSphere.position.copy(this.cameraPositionCache);
}
}
// PlayerState component to attach to the Player GameObject
export class PlayerState extends Behaviour { @serializable(Object3D)
private skyboxSphere: Object3D;
// Method to toggle the skybox sphere visibility
toggleSkyboxVisibility() {
if (this.skyboxSphere) {
this.skyboxSphere.visible = !this.skyboxSphere.visible;
}
}
}
Attach the FixedSkyboxSphere component to the sphere that holds the VideoPlayer. Then, in your PlayerState component, you can call toggleSkyboxVisibility to show or hide the sphere. Ensure the sphere is not a child of the camera or the player-controlled object to prevent it from moving or rotating with the playerās view.
1 messages leftGPT 4 thread_l3uXTfaM2JrKrrFAodYuB3Tv Thanks for your feedback!
To make the 360° sphere follow the player in VR without rotating when the player moves, you can achieve that using the following steps:
Attach the 360° sphere as a child of the VR headset or VR controller to keep it centered.
Track the position of the VR headset or controller and update the position of the 360° sphere to match it without altering its rotation.
Hereās a basic pseudocode to outline the implementation:
// In the VR player script
update() {
// Get the VR headset or controller position
const headsetPosition = getVRHeadsetPosition(); // Function to get VR headset position
// Match the 360° sphere position to the VR headset or controller
sphereGameObject.position.copy(headsetPosition);
}
This will ensure that the 360° sphere stays centered relative to the VR headset or controller, allowing the player to move around while the environment appears stationary.
0 messages leftGPT 3.5 thread_l3uXTfaM2JrKrrFAodYuB3Tv Thanks for your feedback!
In VR the head position is also just the camera position (so using this.context.mainCamera should work, just get the worldPosition, e.g. via this.context.mainCameraComponent.gameObject.worldPosition)
The VideoPlayer component in Needle Engine does not provide an explicit method for detecting if a video clip has ended directly through the API, according to the extracted documentation section (see the documentation). Instead, you can monitor the currentTime property of the VideoPlayer and compare it against the duration of the video element to determine if the video has finished playing.
Hereās a high-level pseudocode for implementing this:
Access the VideoPlayer component on your game object.
Within the update lifecycle method, check if the VideoPlayerās currentTime is equal to or greater than the videoās duration.
If the currentTime is equal to or after the videoās duration, the video has ended.
And the following TypeScript code provides an example of how this might be implemented within a component:
typescript
import { VideoPlayer } from ā@needle-tools/engineā; // Include the correct module path
import { Behaviour } from ā@needle-tools/engineā; // Base class
export class VideoEndDetector extends Behaviour {
private videoPlayer: VideoPlayer;
start() {
// Access the VideoPlayer component from your GameObject
this.videoPlayer = this.gameObject.getComponent(VideoPlayer);
if (!this.videoPlayer) {
console.error("VideoPlayer component not found!");
return;
}
// Optional: start the video if not playing
if (!this.videoPlayer.isPlaying) {
this.videoPlayer.play();
}
}
update() {
// Check if the video is playing and its current time is at the end
if (this.videoPlayer && this.videoPlayer.isPlaying) {
const videoDuration = this.videoPlayer.videoElement.duration;
if (this.videoPlayer.currentTime >= videoDuration) {
// Video has ended
console.log("Video has ended");
// Perform the desired action after the video ends
}
}
}
To ensure that the video duration is always reachable, you may want to add additional checks to confirm the videoās metadata is fully loaded. This approach requires polling during each update call and will allow you to detect when the video has finished playing.
1 messages leftGPT 4 thread_CvD2yBIFfvZOsUBgDDsguQc3 Thanks for your feedback!