Documentation de Needle Engine
Downloads
  • What is Needle Engine?
  • Témoignages
  • Get an overview

    • Samples and Showcase
    • Notre Vision 🔮
    • Aperçu des fonctionnalités
    • Vue d'ensemble technique
  • Resources

    • Pricing and Plans
    • Changelog
    • API Documentation
    • Support & Community
  • Integrations

    • Needle Engine pour Unity
    • Needle Engine pour Blender
    • Needle Engine en tant que composant web
    • Needle Engine sur votre site Web
    • Needle Cloud
  • Topics

    • Structure de projet Web
    • Everywhere Actions
    • Exporter des Assets vers glTF
    • Frameworks, Bundlers, HTML
    • Tester sur les appareils locaux
    • Déploiement et Optimisation
  • Advanced

    • Réseau
    • VR & AR (WebXR)
    • Utiliser Needle Engine directement depuis HTML
    • Synchronisation de l'Editor (Editor Sync)
  • Troubleshooting

    • Comment déboguer
    • Questions et Réponses (FAQ) 💡
    • Get Help
  • Videos

    • Tutorials on Youtube
    • Interviews on Youtube
  • Scripting Overview

    • Scripting in Needle Engine
    • Introduction au Scripting pour les Développeurs Unity
    • Composants principaux de Needle
    • Everywhere Actions
  • Components and Lifecycle

    • Créer et utiliser des Components
    • @serializable et autres décorateurs
    • Génération automatique de composants
    • Exemples de Scripting
    • Community Contributions
    • Modules supplémentaires
  • Settings and APIs

    • <needle-engine> Configuration
    • needle.config.json
    • Needle Engine API
    • three.js API
Help
Samples
Pricing
  • Needle Website
  • Needle Cloud
  • Support Community
  • Discord Server
  • X/Twitter
  • YouTube
  • Newsletter
  • Email
  • Feedback
  • Github
  • English
  • 简体中文
  • Español
  • Português
  • Français
  • हिन्दी
  • 日本語
  • Deutsch
  • Tiếng Việt
Downloads
  • What is Needle Engine?
  • Témoignages
  • Get an overview

    • Samples and Showcase
    • Notre Vision 🔮
    • Aperçu des fonctionnalités
    • Vue d'ensemble technique
  • Resources

    • Pricing and Plans
    • Changelog
    • API Documentation
    • Support & Community
  • Integrations

    • Needle Engine pour Unity
    • Needle Engine pour Blender
    • Needle Engine en tant que composant web
    • Needle Engine sur votre site Web
    • Needle Cloud
  • Topics

    • Structure de projet Web
    • Everywhere Actions
    • Exporter des Assets vers glTF
    • Frameworks, Bundlers, HTML
    • Tester sur les appareils locaux
    • Déploiement et Optimisation
  • Advanced

    • Réseau
    • VR & AR (WebXR)
    • Utiliser Needle Engine directement depuis HTML
    • Synchronisation de l'Editor (Editor Sync)
  • Troubleshooting

    • Comment déboguer
    • Questions et Réponses (FAQ) 💡
    • Get Help
  • Videos

    • Tutorials on Youtube
    • Interviews on Youtube
  • Scripting Overview

    • Scripting in Needle Engine
    • Introduction au Scripting pour les Développeurs Unity
    • Composants principaux de Needle
    • Everywhere Actions
  • Components and Lifecycle

    • Créer et utiliser des Components
    • @serializable et autres décorateurs
    • Génération automatique de composants
    • Exemples de Scripting
    • Community Contributions
    • Modules supplémentaires
  • Settings and APIs

    • <needle-engine> Configuration
    • needle.config.json
    • Needle Engine API
    • three.js API
Help
Samples
Pricing
  • Needle Website
  • Needle Cloud
  • Support Community
  • Discord Server
  • X/Twitter
  • YouTube
  • Newsletter
  • Email
  • Feedback
  • Github
  • English
  • 简体中文
  • Español
  • Português
  • Français
  • हिन्दी
  • 日本語
  • Deutsch
  • Tiếng Việt
  • Getting Started

    • Downloads
    • Needle Engine for Unity
    • Needle Engine for Blender
    • Needle Engine as Web Component
    • Needle Engine on your Website
    • Needle Cloud
    • Custom integrations
    • Support and Community
  • Core Concepts

    • Structure de projet Web
    • Everywhere Actions
    • Exporter des Assets vers glTF
    • Frameworks, Bundlers, HTML
    • Tester sur les appareils locaux
    • Déploiement et Optimisation
    • Comment déboguer
    • Questions et Réponses (FAQ) 💡
  • Scripting

    • Scripting in Needle Engine
    • Introduction au Scripting pour les Développeurs Unity
    • Créer et utiliser des Components
    • Génération automatique de composants
    • Exemples de Scripting
    • Community Contributions
  • Advanced

    • VR & AR (WebXR)
    • Réseau
    • Synchronisation de l'Editor (Editor Sync)
  • Reference

    • Aperçu des fonctionnalités
    • Vue d'ensemble technique
    • Composants principaux de Needle
    • needle.config.json
    • <needle-engine> Configuration
    • @serializable et autres décorateurs

Créer des composants personnalisés

Si vous débutez en scripting, nous vous recommandons fortement de lire d'abord les guides suivants :

  • Principes essentiels de Typescript
  • Needle Engine pour les développeurs Unity

Si vous savez ce que vous faites, n'hésitez pas à consulter directement la documentation API de Needle Engine.


Le code d'exécution pour Needle Engine est écrit en TypeScript (recommandé) ou en JavaScript. Nous générons automatiquement des composants C# stub à partir de cela, que vous pouvez ajouter aux GameObjects dans l'éditeur. Les composants C# et leurs données sont recréés par le runtime en tant que composants JavaScript avec les mêmes données et attachés aux objets three.js.

Les composants personnalisés ainsi que les composants Unity intégrés peuvent être mappés en composants JavaScript de cette manière. Par exemple, les mappages pour de nombreux composants intégrés liés à l'animation, au rendu ou à la physique sont déjà inclus dans Needle Engine.

Si vous souhaitez suivre les exemples suivants sans rien installer, cliquez simplement sur le lien suivant :

  • Créer un espace de travail virtuel pour coder.

Notre moteur d'exécution web adopte un modèle de composant similaire à Unity et offre ainsi de nombreuses fonctionnalités qui vous seront familières. Les composants attachés aux objets three.js Object3D ont des méthodes de cycle de vie comme awake, start, onEnable, onDisable, update et lateUpdate que vous pouvez implémenter. Vous pouvez également utiliser des Coroutines.


Quand vous n'avez pas besoin d'écrire de code

Souvent, les scènes interactives peuvent être réalisées en utilisant des Events dans Unity et en appelant des méthodes sur des composants intégrés. Un exemple typique est de jouer une animation sur un clic de bouton - vous créez un bouton, ajoutez un événement Click dans l'inspector, et le faites appeler Animator.SetTrigger ou similaire pour jouer une animation spécifique.

Needle Engine traduit les Unity Events en appels de méthodes JavaScript, ce qui en fait un flux de travail très rapide et flexible - configurez vos événements comme d'habitude et lorsqu'ils sont appelés, ils fonctionneront de la même manière que dans Unity.

imageUn exemple d'événement Button Click fonctionnant immédiatement dans Needle Engine — aucun code n'est nécessaire.

Créer un nouveau composant

Les scripts sont écrits en TypeScript (recommandé) ou JavaScript. Il existe deux façons d'ajouter des scripts personnalisés à votre projet :

  • Ajoutez simplement un fichier avec une extension .ts ou .js à l'intérieur de src/scripts/ dans le répertoire de votre projet généré, par exemple src/scripts/MyFirstScript.ts.

  • Spécifique à Unity : Organisez votre code en fichiers de définition NPM (paquets npm). Ceux-ci vous aident à modulariser et réutiliser le code entre les projets et si vous êtes familier avec le développement web, ce sont en fait des paquets npm réguliers qui sont installés localement. Dans Unity, vous pouvez créer des fichiers NpmDef via Create > NPM Definition, puis ajouter des fichiers TypeScript en cliquant droit sur un fichier NpmDef et en sélectionnant Create > TypeScript. Veuillez consulter ce chapitre pour plus d'informations.

Dans les deux approches, les répertoires source sont surveillés pour les modifications et les composants C# stub ou les panneaux Blender sont régénérés chaque fois qu'une modification est détectée. Les modifications apportées aux fichiers source entraînent également un rechargement à chaud du site web en cours d'exécution – vous n'avez pas à attendre que Unity recompile les composants C#. Cela rend l'itération sur le code quasiment instantanée.

Vous pouvez même avoir plusieurs types de composants dans un seul fichier (par exemple, vous pouvez déclarer export class MyComponent1 et export class MyOtherComponent dans le même fichier Typescript).

Si vous débutez dans l'écriture de Javascript ou Typescript, nous vous recommandons de lire d'abord le guide Principes essentiels de Typescript avant de continuer avec ce guide.

Exemple : Créer un composant qui fait pivoter un objet
  • Créer un composant qui fait pivoter un objet Créer src/scripts/Rotate.ts et ajouter le code suivant :
import { Behaviour, serializable } from "@needle-tools/engine";

export class Rotate extends Behaviour
{
    @serializable()
    speed : number = 1;

    start(){
        // logging this is useful for debugging in the browser.
        // You can open the developer console (F12) to see what data your component contains
        console.log(this);
    }

    // update will be called every frame
    update(){
        this.gameObject.rotateY(this.context.time.deltaTime * this.speed);
    }
}

Maintenant, dans Unity, un nouveau script appelé Rotate.cs sera automatiquement généré. Ajoutez le nouveau composant Unity à un Cube et sauvegardez la scène. Le cube tourne maintenant dans le navigateur. Ouvrez la console de développement chrome avec F12 pour inspecter le log de la méthode Rotate.start. C'est une pratique utile pour apprendre et déboguer quels champs sont exportés et actuellement assignés. En général, tous les champs publics et sérialisables ainsi que toutes les propriétés publiques sont exportés.

Ajoutez maintenant un nouveau champ public float speed = 5 à votre composant Unity et sauvegardez-le. L'inspector du composant Rotate affiche maintenant un champ speed que vous pouvez modifier. Sauvegardez la scène (ou cliquez sur le bouton Build) et notez que le composant javascript a maintenant la valeur speed exportée assignée.

Créer un composant avec une fonction personnalisée

Référez-vous au Guide des principes essentiels de Typescript pour en savoir plus sur la syntaxe et le langage.

import { Behaviour } from "@needle-tools/engine";

export class PrintNumberComponent extends Behaviour
{
    start(){
      this.printNumber(42);
    }

    private printNumber(myNumber : number){
        console.log("My Number is: " + myNumber);
    }
}
Gestion de version et Unity

Bien que les composants C# générés utilisent le nom du type pour produire des GUID stables, nous recommandons d'enregistrer les composants générés dans le contrôle de version comme bonne pratique.

Architecture des composants

Les composants sont ajoutés aux Object3Ds de three.js. Cela est similaire à la façon dont les Components dans Unity sont ajoutés aux GameObjects. Par conséquent, lorsque nous voulons accéder à un Object3D de three.js, nous pouvons y accéder en tant que this.gameObject, qui retourne le Object3D auquel le composant est attaché.

Note : Mettre visible à false sur un Object3D agira comme SetActive(false) dans Unity - ce qui signifie que cela désactivera également tous les composants actuels sur cet objet et ses enfants. Les événements Update pour les composants inactifs ne sont pas appelés tant que visible n'est pas remis à true. Si vous souhaitez masquer un objet sans affecter les composants, vous pouvez simplement désactiver le composant Needle Engine Renderer.

Méthodes de cycle de vie

Notez que les méthodes de cycle de vie ne sont appelées que lorsqu'elles sont déclarées. Il ne faut donc déclarer les méthodes de cycle de vie update que lorsqu'elles sont réellement nécessaires, sinon cela peut nuire aux performances si vous avez de nombreux composants avec des boucles d'update qui ne font rien.

Nom de la méthodeDescription
awake()Première méthode appelée lors de la création d'un nouveau composant
onEnable()Appelée lorsqu'un composant est activé (par exemple lorsque enabled passe de false à true)
onDisable()Appelée lorsqu'un composant est désactivé (par exemple lorsque enabled passe de true à false)
onDestroy()appelée lorsque l'Object3D ou le composant est détruit
start()Appelée au début de la première image après la création du composant
earlyUpdate()Premier événement de mise à jour
update()Événement de mise à jour par défaut
lateUpdate()Appelée après update
onBeforeRender()Dernier événement de mise à jour avant l'appel de rendu
onAfterRender()Appelée après l'événement de rendu

Méthodes d'événement physique

Nom de la méthodeDescription
onCollisionEnter(col : Collision)
onCollisionStay(col : Collision)
onCollisionExit(col : Collision)
onTriggerEnter(col : Collision)
onTriggerStay(col : Collision)
onTriggerExit(col : Collision)

Méthodes d'événement d'entrée

Nom de la méthodeDescription
onPointerEnter(args : PointerEventData)Appelée lorsqu'un curseur commence à survoler un objet (ou l'un de ses enfants)
onPointerMove(args : PointerEventData)Appelée lorsqu'un curseur se déplace sur un objet (ou l'un de ses enfants)
onPointerExit(args : PointerEventData)Appelée lorsqu'un curseur quitte (arrête de survoler) un objet
onPointerDown(args : PointerEventData)Appelée lorsqu'un curseur est pressé sur un objet
onPointerUp(args : PointerEventData)Appelée lorsqu'un curseur est relâché sur un objet
onPointerClick(args : PointerEventData)Appelée lorsqu'un curseur est cliqué sur un objet

Méthodes d'événement XR

nécessite Needle Engine >= 3.32.0

Nom de la méthodeDescription
supportsXR(mode: XRSessionMode)Optionnellement implémenté si vous souhaitez ne recevoir des callbacks XR que pour des modes XR spécifiques comme immersive-vr ou immersive-ar. Retourne true pour notifier le système que vous souhaitez des callbacks pour le mode passé.
onBeforeXR(mode: XRSessionMode, init: XRSessionInit)Appelé juste avant qu'une XRSession soit demandée et peut être utilisé pour modifier l'objet XRSessionInit
onEnterXR(args: NeedleXREventArgs)Callback lorsque ce composant rejoint une session xr (ou devient actif dans une session XR en cours)
onUpdateXR(args: NeedleXREventArgs)Callback lorsqu'une session xr est mise à jour (tant qu'elle est encore active dans la session XR)
onLeaveXR(args: NeedleXREventArgs)Callback lorsque ce composant quitte une session xr (ou lorsqu'il devient inactif dans une session XR en cours)
onControllerAdded(args: NeedleXRControllerEventArgs)Callback lorsqu'un contrôleur est connecté/ajouté pendant une session XR OU lorsque le composant rejoint une session XR en cours qui a déjà des contrôleurs connectés OU lorsque le composant devient actif pendant une session XR en cours qui a déjà des contrôleurs connectés
onControllerRemoved(args: NeedleXRControllerEventArgs)Callback lorsqu'un contrôleur est supprimé pendant une session XR OU lorsque le composant devient inactif pendant une session XR en cours

Événements XR supplémentaires

Nom de la méthodeDescription
window.addEventListener("needle-xrsession-start")CustomEvent qui est invoqué lorsqu'une XRSession démarre. details contient la NeedleXRSession
window.addEventListener("needle-xrsession-end")CustomEvent qui est invoqué lorsqu'une XRSession se termine. details contient la NeedleXRSession
onXRSessionStart(args: { session:NeedleXRSession } )hook d'événement global. Pour se désabonner, utiliser offXRSessionStart

Coroutines

Les Coroutines peuvent être déclarées en utilisant la syntaxe JavaScript Generator. Pour démarrer une coroutine, appelez this.startCoroutine(this.myRoutineName());

Exemple

import { Behaviour, FrameEvent } from "@needle-tools/engine";

export class Rotate extends Behaviour {

    start() {
        // the second argument is optional and allows you to specifiy
        // when it should be called in the current frame loop
        // coroutine events are called after regular component events of the same name
        // for example: Update coroutine events are called after component.update() functions
        this.startCoroutine(this.rotate(), FrameEvent.Update);
    }

    // this method is called every frame until the component is disabled
    *rotate() {
        // keep looping forever
        while (true) {
            yield;
        }
    }
}

Pour arrêter une coroutine, soit vous quittez la routine en y retournant, soit vous mettez en cache la valeur de retour de startCoroutine et appelez this.stopCoroutine(<...>). Toutes les Coroutines sont arrêtées à onDisable / lors de la désactivation d'un composant.

Hooks de cycle de vie spéciaux

Needle Engine expose également quelques hooks de cycle de vie que vous pouvez utiliser pour vous brancher sur la boucle de mise à jour sans avoir à écrire un composant complet. Ces hooks peuvent être insérés à n'importe quel point de votre application web (par exemple dans la portée de niveau supérieur ou dans un composant svelte)

Nom de la méthodeDescription
onInitialized(cb, options)Appelé lorsqu'un nouveau contexte est initialisé (avant la première image)
onClear(cb, options)Enregistre un callback avant que le contexte du moteur ne soit effacé
onDestroy(cb, options)Enregistre un callback dans le moteur avant que le contexte ne soit détruit
onStart(cb, options)Appelé directement après le start des composants au début d'une image
onUpdate(cb, options)Appelé directement après l'update des composants
onBeforeRender(cb, options)Appelé avant l'appel de rendu
onAfterRender(cb, options)Appelé après l'appel de rendu

Par exemple (Voir l'exemple sur stackblitz)

// this can be put into e.g. main.ts or a svelte component (similar to onMount)
import { onStart, onUpdate, onBeforeRender, onAfterRender } from "@needle-tools/engine"

onStart(ctx => console.log("Hello Scene", ctx.scene));

onUpdate(ctx => {
    // do something... e.g. access the frame # or deltatime via ctx.time
    console.log("UPDATE", ctx.time.frame);
});

onBeforeRender(ctx => {
    // this event is only called once because of the { once: true } argument
    console.log("ON BEFORE RENDER", ctx.time.frame);
}, { once: true } );

// Every event hook returns a method to unsubscribe from the event
const unsubscribe = onAfterRender(ctx => {
    console.log("ON AFTER RENDER", ctx.time.frame);
});
// Unsubscribe from the event at any time
setTimeout(()=> unsubscribe(), 1000);

Trouver, ajouter et supprimer des composants

Pour accéder à d'autres composants, utilisez les méthodes statiques sur GameObject ou les méthodes this.gameObject. Par exemple, pour accéder à un composant Renderer dans le parent, utilisez GameObject.getComponentInParent(this.gameObject, Renderer) ou this.gameObject.getComponentInParent(Renderer).

Exemple :

import { Behaviour, GameObject, Renderer } from "@needle-tools/engine";

export class MyComponent extends Behaviour {

    start() {
        const renderer = GameObject.getComponentInParent(this.gameObject, Renderer);
        console.log(renderer);
    }
}

Quelques-unes des méthodes disponibles :

Méthode
GameObject.instantiate(Object3D, InstantiateOptions)crée une nouvelle instance de cet objet incluant de nouvelles instances de tous ses composants
GameObject.destroy(Object3D | Component)détruit un composant ou Object3D (et ses composants)
GameObject.addNewComponent(Object3D, Type)ajoute (et crée) un nouveau composant pour un type à l'objet fourni. Notez que awake et onEnable sont déjà appelés lorsque le composant est retourné.
GameObject.addComponent(Object3D, Component)déplace une instance de composant vers l'objet fourni. C'est utile si vous avez déjà une instance, par exemple lorsque vous créez un composant avec new MyComponent() et que vous l'attachez ensuite à un objet.
GameObject.removeComponent(Component)supprime un composant d'un gameObject
GameObject.getComponent(Object3D, Type)retourne le premier composant correspondant à un type sur l'objet fourni.
GameObject.getComponents(Object3D, Type)retourne tous les composants correspondant à un type sur l'objet fourni.
GameObject.getComponentInChildrenidem que getComponent mais recherche également dans les objets enfants.
GameObject.getComponentsInChildrenidem que getComponents mais recherche également dans les objets enfants.
GameObject.getComponentInParentidem que getComponent mais recherche également dans les objets parents.
GameObject.getComponentsInParentidem que getComponents mais recherche également dans les objets parents.
GameObject.findObjectOfTyperecherche dans toute la scène un type.
GameObject.findObjectsOfTyperecherche dans toute la scène tous les types correspondants.

Three.js et le DOM HTML

Le contexte fait référence au runtime à l'intérieur d'un web component. La scène three.js se trouve à l'intérieur d'un composant HTML personnalisé appelé <needle-engine> (voir le fichier index.html dans votre projet). Vous pouvez accéder au web component <needle-engine> en utilisant this.context.domElement.

Cette architecture permet potentiellement d'avoir plusieurs scènes Needle WebGL sur la même page web, qui peuvent soit s'exécuter indépendamment, soit communiquer entre elles en tant que parties de votre page web.

Accéder à la scène

Pour accéder à la scène actuelle depuis un composant, utilisez this.scene, ce qui est équivalent à this.context.scene. Cela vous donne l'objet racine de la scène three.js.

Pour parcourir la hiérarchie à partir d'un composant, vous pouvez soit itérer sur les enfants d'un objet avec une boucle for :

for(let i = 0; i < this.gameObject.children; i++)
    console.log(this.gameObject.children[i]);

ou vous pouvez itérer en utilisant l'équivalent de foreach :

for(const child of this.gameObject.children) {
    console.log(child);
}

Vous pouvez également utiliser des méthodes spécifiques à three.js pour itérer rapidement tous les objets récursivement en utilisant la méthode traverse :

import { Object3D } from "three";
this.gameObject.traverse((obj: Object3D) => console.log(obj));

ou pour parcourir uniquement les objets visibles, utilisez traverseVisible à la place.

Une autre option très utile lorsque vous souhaitez simplement itérer sur les objets pouvant être rendus est de interroger tous les composants renderer et d'itérer sur eux comme suit :

import { Renderer } from "@needle-tools/engine";
for(const renderer of this.gameObject.getComponentsInChildren(Renderer))
    console.log(renderer);

Pour plus d'informations sur l'obtention de composants, consultez la section suivante.

Temps

Utilisez this.context.time pour accéder aux données temporelles :

  • this.context.time.time est le temps écoulé depuis le début de l'exécution de l'application
  • this.context.time.deltaTime est le temps écoulé depuis la dernière frame
  • this.context.time.frameCount est le nombre de frames écoulées depuis le début de l'application
  • this.context.time.realtimeSinceStartup est le temps non mis à l'échelle écoulé depuis le début de l'exécution de l'application

Il est également possible d'utiliser this.context.time.timeScale pour ralentir délibérément le temps, par exemple pour des effets de ralenti.

Entrée

Recevoir les données d'entrée pour l'objet sur lequel se trouve le composant :

import { Behaviour } from "@needle-tools/engine";
export class MyScript extends Behaviour
{
    onPointerDown() {
        console.log("POINTER DOWN sur " + this.gameObject.name);
    }
}

Vous pouvez également vous abonner à des événements globaux dans l'énumération InputEvents comme ceci :

import { Behaviour, InputEvents, NEPointerEvent } from "@needle-tools/engine";

export class MyScript extends Behaviour
{
    onEnable() {
        this.context.input.addEventListener(InputEvents.PointerDown, this.inputPointerDown);
    }

    onDisable() {
        // it is recommended to also unsubscribe from events when your component becomes inactive
        this.context.input.removeEventListener(InputEvents.PointerDown, this.inputPointerDown);
    }

    // @nonSerialized
    inputPointerDown = (evt: NEPointerEvent) => { console.log("POINTER DOWN partout sur l'élément <needle-engine>"); }
}

Ou utilisez this.context.input si vous souhaitez interroger l'état de l'entrée à chaque frame :

import { Behaviour } from "@needle-tools/engine";
export class MyScript extends Behaviour
{
    update() {
        if(this.context.input.getPointerDown(0)){
            console.log("POINTER DOWN partout")
        }
    }
}

Si vous souhaitez gérer les entrées vous-même, vous pouvez également vous abonner à tous les événements fournis par le navigateur (il y en a une tonne). Par exemple, pour vous abonner à l'événement click du navigateur, vous pouvez écrire :

import { Behaviour } from "@needle-tools/engine";
export class MyScript extends Behaviour
{
    onEnable() {
        window.addEventListener("click", this.windowClick);
    }

    onDisable() {
        // unsubscribe again when the component is disabled
        window.removeEventListener("click", this.windowClick);
    }

    windowClick = () => { console.log("CLIC partout sur la page, pas seulement sur <needle-engine>"); }
}

Notez que dans ce cas, vous devez gérer vous-même tous les cas. Par exemple, vous pourriez avoir besoin d'utiliser différents événements si votre utilisateur visite votre site web sur un ordinateur de bureau, sur mobile ou sur un appareil VR. Ces cas sont gérés automatiquement par les événements d'entrée de Needle Engine (par exemple, PointerDown est déclenché à la fois pour le clic de souris, le toucher tactile et, dans le cas de la VR, pour le bouton du contrôleur).

Raycasting

Utilisez this.context.physics.raycast() pour effectuer un lancer de rayon et obtenir une liste d'intersections. Si vous ne passez aucune option, le lancer de rayon est effectué depuis la position de la souris (ou la première position tactile) dans l'espace écran en utilisant la mainCamera actuellement active. Vous pouvez également passer un objet RaycastOptions qui contient diverses options comme maxDistance, la caméra à utiliser ou les calques à tester.

Utilisez this.context.physics.raycastFromRay(your_ray) pour effectuer un lancer de rayon en utilisant un rayon three.js.

Note : Ce type de lancer de rayon lance un rayon contre tous les objets visibles dans la scène. Aucun moteur physique n'est nécessaire, ce qui est différent du comportement dans Unity, où vous avez toujours besoin de colliders pour toucher les objets. Si vous voulez lancer uniquement contre les colliders physiques, utilisez les méthodes physics.engine.raycast décrites ci-dessous.

Considérations sur les performances

Lors de l'utilisation des paramètres de compression par défaut de Needle, des versions simplifiées des maillages sont automatiquement créées et utilisées également pour le lancer de rayons. Néanmoins, certains types de maillages sont lents – par exemple, les maillages skinnés ou les maillages avec blendshapes nécessitent des calculs coûteux pour déterminer les coups exacts. Considérez de définir ces objets sur le calque Ignore Raycast dans Unity pour éviter le lancer de rayons contre eux.

Raycasting basé sur la physique

Une autre option est d'utiliser les méthodes de lancer de rayons physiques qui ne retourneront que les hits avec les colliders dans la scène.

const hit = this.context.physics.engine?.raycast();

Voici un exemple éditable de raycast physique

Réseau

Les méthodes réseau sont accessibles via this.context.connection. Veuillez vous référer à la documentation réseau pour plus d'informations.

Accéder à Needle Engine et aux composants depuis n'importe où

Il est possible d'accéder à toutes les fonctionnalités décrites ci-dessus en utilisant du code JavaScript régulier qui n'est pas à l'intérieur de composants et qui se trouve ailleurs. Tous les composants et fonctionnalités du runtime Needle sont accessibles via l'espace de noms global Needle (vous pouvez écrire console.log(Needle) pour avoir un aperçu)

Vous pouvez trouver des composants en utilisant Needle.findObjectOfType(Needle.AudioSource) par exemple. Il est recommandé de mettre en cache ces références, car chercher dans toute la scène à plusieurs reprises est coûteux. Voir la liste pour trouver, ajouter et supprimer des composants ci-dessus.

Pour obtenir des callbacks pour le chargement initial de la scène, voir l'exemple suivant :

<needle-engine loadstart="loadingStarted" progress="loadingProgress" loadfinished="loadingFinished"></needle-engine>

<script type="text/javascript">
function loadingStarted() { console.log("START") }
function loadingProgress() { console.log("LOADING...") }
function loadingFinished() { console.log("FINISHED!") }
</script>

Vous pouvez également vous abonner à l'événement global NeedleEngine (parfois aussi appelé ContextRegistry) pour recevoir un callback lorsqu'un contexte Needle Engine a été créé ou pour accéder à tous les contextes disponibles :

class YourComponentType extends Behaviour {}
//---cut---
import { NeedleEngine, GameObject, Behaviour } from "@needle-tools/engine";

NeedleEngine.addContextCreatedCallback((args) => {
  const context = args.context;
  const scene = context.scene;
  const myInstance = GameObject.getComponentInChildren(scene, YourComponentType);
});

Une autre option est d'utiliser le hook de cycle de vie onInitialized(ctx => {}) special.

Vous pouvez également accéder à tous les contextes disponibles via NeedleEngine.Registered qui renvoie le tableau interne. (Notez que ce tableau ne doit pas être modifié mais peut être utilisé pour itérer sur tous les contextes actifs afin de modifier les paramètres, par exemple, définir tous les contextes sur context.isPaused = true).

Ci-dessous, vous trouverez une liste des événements disponibles sur le type statique NeedleEngine. Vous pouvez vous abonner à ces événements via NeedleEngine.registerCallback(ContextEvent.ContextCreated, (args) => {})

Options ContextEvent
ContextEvent.ContextRegisteredAppelé lorsque le contexte est enregistré dans le registre.
ContextEvent.ContextCreationStartAppelé avant le chargement du premier glb et peut être utilisé pour initialiser le moteur physique. Peut retourner une promesse
ContextEvent.ContextCreatedAppelé lorsque le contexte a été créé avant la première image
ContextEvent.ContextDestroyedAppelé lorsque le contexte a été détruit
ContextEvent.MissingCameraAppelé lorsque le contexte n'a pas pu trouver de caméra, actuellement appelé uniquement pendant la création
ContextEvent.ContextClearingAppelé lorsque le contexte est en cours d'effacement : tous les objets de la scène sont détruits et l'état interne est réinitialisé
ContextEvent.ContextClearedAppelé après que le contexte a été effacé

Gizmos

La classe statique Gizmos peut être utilisée pour dessiner des lignes, des formes et du texte, ce qui est principalement utile pour le débogage. Toutes les fonctions de gizmos ont plusieurs options pour, par exemple, les couleurs ou la durée pendant laquelle elles doivent être affichées dans la scène. En interne, elles sont mises en cache et réutilisées.

Gizmos
Gizmos.DrawLabelDessine une étiquette avec un arrière-plan optionnel. Elle peut être attachée à un objet. Retourne un handle Label qui peut être utilisé pour mettre à jour le texte.
Gizmos.DrawRayPrend une origine et une direction en espace monde pour dessiner une ligne de rayon infinie
Gizmos.DrawDirectionPrend une origine et une direction pour dessiner une direction en espace monde
Gizmos.DrawLinePrend deux points vec3 en espace monde pour dessiner une ligne
Gizmos.DrawWireSphereDessine une sphère en fil de fer en espace monde
Gizmos.DrawSphereDessine une sphère pleine en espace monde
Gizmos.DrawWireBoxDessine une boîte en fil de fer en espace monde
Gizmos.DrawWireBox3Dessine une boîte3 en fil de fer
Gizmos.DrawArrowDessine une flèche prenant deux points en espace monde

Sérialisation / Composants dans les fichiers glTF

Pour intégrer des composants et recréer des composants avec leurs types corrects en glTF, nous devons également enregistrer des types non primitifs (tout ce qui n'est pas un Number, Boolean ou String). Vous pouvez le faire en ajoutant un décorateur @serializable(<type>) au-dessus de votre champ ou propriété.

Exemple :

import { Behaviour, serializable, Camera } from "@needle-tools/engine";
import { Object3D } from "three"

export class MyClass extends Behaviour {
    // this will be a "Transform" field in Unity
    @serializable(Object3D) 
    myObjectReference: Object3D | null = null;
    
    // this will be a "Transform" array field in Unity
    // Note that the @serializable decorator contains the array content type! (Object3D and not Object3D[])
    @serializable(Object3D) 
    myObjectReferenceList: Object3D[] | null = null;

    // for component or other objects use the object's type
    @serializable(Camera)
    myCameraComponent: Camera | null = null;
}

Pour sérialiser vers et depuis des formats personnalisés, il est possible d'étendre la classe TypeSerializer et de créer une instance. Utilisez super() dans le constructeur pour enregistrer les types pris en charge.

Note : En plus des champs correspondants, les propriétés correspondantes seront également exportées si elles correspondent à des champs dans le fichier typescript.

Chargement de scènes

Dans Unity, les Prefabs référencés, les SceneAssets et les AssetReferences (système Addressable de Unity) seront automatiquement exportés sous forme de fichiers glTF (veuillez vous référer à la documentation Exporter les Prefabs).

Ces fichiers gltf exportés seront sérialisés sous forme d'URIs de chaîne de caractères simples. Pour simplifier leur chargement à partir de composants TypeScript, nous avons ajouté le concept de types AssetReference. Ils peuvent être chargés au runtime et permettent ainsi de différer le chargement de parties de votre application ou le chargement de contenu externe.

Exemple :

import { Behaviour, serializable, AssetReference } from "@needle-tools/engine";

export class MyClass extends Behaviour {

    // if you export a prefab or scene as a reference from Unity you'll get a path to that asset
    // which you can de-serialize to AssetReference for convenient loading
    @serializable(AssetReference)
    myPrefab?: AssetReference;
    
    async start() {
      // directly instantiate
      const myInstance = await this.myPrefab?.instantiate();

      // you can also just load and instantiate later
      // const myInstance = await this.myPrefab.loadAssetAsync();
      // this.gameObject.add(myInstance)
      // this is useful if you know that you want to load this asset only once because it will not create a copy
      // since ``instantiate()`` does create a copy of the asset after loading it
    }  
}

Les AssetReferences sont mis en cache par URI, donc si vous référencez le même glTF/Prefab exporté dans plusieurs composants/scripts, il ne sera chargé qu'une seule fois et ensuite réutilisé.

Prochaines étapes


Page automatiquement traduite par IA

Suggest changes
Dernière mise à jour:: 22/04/2025 11:01
Prev
Introduction au Scripting pour les Développeurs Unity
Next
Génération automatique de composants