im trying to pass array of AudioClips to this script, but it wont show up in the editor. Is this the wrong AudioClip class?
You can see the old C# script that im converting to TS (it’s disabled). You can see it has a public AudioClips array that shows in editor. That’s how the new TS script should be too.
Original Post on Discord
by user 352282921056468993
Audio clips are at runtime in the browser just urls. So you’ll receive string[]
AudioClipModel is a special type from the timeline
Make sure to make using serializable()
a habit too
@serializable()
audioClips : string[];
@serializable(Object3D)
myObjectReference : Object3D;
@serializable(Object3D)
myObjects : Object3D[]
you can omit the type parameter in serializable()
for strings, numbers, bools (js primitive types) and for arrays it’s the array content type (see third example above
)
If you want to use codegen with audioclips you can do a little trick like this:
// declare custom AudioClip type somewhere
type AudioClip = string;
// in your script:
@serializable()
myClips : AudioClip[]; // < the component compiler will use known types, in this case it'll know AudioClip from UnityEngine.AudioClip
Ahh amazing i think that will work. Is there a certain folder assets should go in for a Needle project? I ask because when AudioClip tries to play i get this error here.
Also, i see in the web project assets folder that these assets did transfer from unity, so im a bit confused why they are not found
by user 352282921056468993
Are you trying to use them directly? Then try call resolveUrl(this.sourceIdentifier, myAudioClipUrl)
from your script
was using them like this. I’ll try resolveUrl if i can figure out what to put for the arguments
by user 352282921056468993
this.audioSource.play(this.audioClips[i])
should work as well
resolveUrl(this.sourceIdentifier, yourUrl)
is what you use - but you dont have to if you use the AudioSource and set the clip there
So there’s a way to do it without AudioSource? How’s that work? The resolveUrl stuff worked to fix those errors, but still didnt play audio. Just gave warning in console saying “failed getting sound.” - I think may be due to bug in AudioSource. Right here it uses “this.Sound” but everywhere else it uses “this.sound”
by user 352282921056468993
here’s warning in console in case that’s useful
by user 352282921056468993
Can you share your code again?
If you just want to play the clip you can use the three audio code yourself or just a html audio element
(depending on your needs)
import { AudioSource, Behaviour, GameObject, Text, resolveUrl, serializable } from "@needle-tools/engine"
type AudioClip = string;
export class SubtitleController extends Behaviour {
@serializable()
audioClips: AudioClip[]
public subtitles: string[]
@serializable()
private audioSource: AudioSource
private tMP_Text: Text
public blankTimeAtEnd: number[]
public upperDoor: GameObject
public videoPanel: GameObject
constructor() {
super()
this.audioClips = []
this.subtitles = []
this.blankTimeAtEnd = []
}
start() {
this.audioSource = this.gameObject.getComponent(AudioSource) as any
console.log('audioSource==', this.audioSource)
this.tMP_Text = this.gameObject.getComponent(Text) as any
if (this.gameObject.name !== "market down") {
this.audio()
}
}
async audio() {
if (this.gameObject.name === "intro") {
await new Promise(resolve => setTimeout(resolve, 2000))
}
for (let i = 0; i < this.audioClips.length; i++) {
this.audioSource.clip = this.audioClips[i]
this.tMP_Text.text = this.subtitles[i]
// this.audioSource.play(this.audioSource.clip)
this.audioSource.play(resolveUrl(this.sourceId, this.audioSource.clip))
await new Promise(resolve => setTimeout(resolve, (this.audioClips[i].length + this.blankTimeAtEnd[i]) * 1000))
if (i === this.audioClips.length - 1) {
this.tMP_Text.text = ""
if (this.gameObject.name === "intro") {
this.upperDoor.traverse((entity) => {
const audioComponent = entity.getComponent(AudioSource)
if (audioComponent) {
audioComponent.play()
}
})
}
}
}
}
}
by user 352282921056468993
can you do this same thing with AudioSource? But it’s not a string so would you just do type AudioSource = any;
?
by user 352282921056468993
You dont need to do it for audiosource because it already matches the type name in unity (UnityEngine.AudioSource)
Its only relevant if your c# component is being generated from typescript btw
i tried this same thing with SceneManager
from Unity, but it didnt work. Although it’s used a bit differently in this new context. I did this:
type SceneManager = any;
@serializable()
private sceneManager: SceneManager
start() {
this.sceneManager = new SceneManager()
}
but it still doesnt know what SceneManager is - it ends up undefined
by user 352282921056468993
If it doesnt find the type you can annotate it too, one second