Forum Discussion

X_Wookie_X's avatar
9 months ago
Solved

Needing script that randomly moves objects withing a defined area.

  • So all of the animations in Puddin’s perfect phish tank are calculated and done on update with move to and rotate to. I am using Perlin noise to create a rotation for the head, and each subsequent body part repeats the rotation with a delay and a degree of amplification. it’s the same script I use to animate my flags. Then I use the forward direction of the head to actually move the fish. Perlin is great for this type of smooth movement because it always contains its own acceleration. The further you zoom in, the smoother the motion is. The noise contains every point between a and B and you get to control the speed  

8 Replies

  • You will not need typescript for this. Just use code blocks. This demonstrates how you would move the object, but you will have to finish the rest of the script. There are primarily three code blocks you will need: "move to", "random  number with decimals", and "new vector from xyz". You will need to adjust the Min and Max on each axis for your defined area, but this script on it's own would just move itself to a new random location every 10 seconds. Try this and experiment with the numbers to see what changes.

     

    • HomeMed's avatar
      HomeMed
      Partner

      I would suggest using "Move By" at line 7 rather than "Move To", otherwise the object will move to those position rather than moving at the location it is at. Also if you want to see the object move then use "Move by over time"

  • It looks like you're wanting a Typescript version. What I like to do is set a central object that I can move around if needed then I can move my other objects by a random min/max value based on the central objects location.


    You didn't specify if you wanted the objects to move instantly or overtime and you didn't specify if you wanted the move on all 3 axis or just 2. If you can answer those questions then I may be able to provide an example for you.

    • X_Wookie_X's avatar
      X_Wookie_X
      Member

      Sorry, yes I want them seen and yes all 3 axis...basically I'm wanting to have fish swim around smoothly but also randomly

    • jimpuddin's avatar
      jimpuddin
      Meta Employee

      So all of the animations in Puddin’s perfect phish tank are calculated and done on update with move to and rotate to. I am using Perlin noise to create a rotation for the head, and each subsequent body part repeats the rotation with a delay and a degree of amplification. it’s the same script I use to animate my flags. Then I use the forward direction of the head to actually move the fish. Perlin is great for this type of smooth movement because it always contains its own acceleration. The further you zoom in, the smoother the motion is. The noise contains every point between a and B and you get to control the speed  

  • This will set a min and max position for the object and randomly select a position within those values. Once selected it will move that object towards that position and rotate the object to look at that position. This is done on update using lerp and slerp respectively.

    I did test this and seems to be working towards your specifications. Note that you will have to place this on the object that is supposed to move and set the offset values in the inspector. The moving object will be in the center of the area you desire it to move on start.

    import { Component, PropTypes, Vec3, World, Quaternion} from 'horizon/core';
    
    class RandomMoveWithinArea extends Component<typeof RandomMoveWithinArea> {
        static propsDefinition = {
            xOffset: { type: PropTypes.Number, default: 0 },
            yOffset: { type: PropTypes.Number, default: 0 },
            zOffset: { type: PropTypes.Number, default: 0 },
            moveSpeed: { type: PropTypes.Number, default: 1 },
        };
    
        private maxPos: Vec3 = new Vec3(0, 0, 0);
        private minPos: Vec3 = new Vec3(0, 0, 0);
        private startPosition: Vec3 = new Vec3(0, 0, 0);
        private targetPosition: Vec3 = new Vec3(0, 0, 0);
    
        private startTime: number = 0;
        private elapsedTime: number = 0;
        private duration: number = 10000;
    
        private isMoving: boolean = false
    
    
        start() {
            this.connectLocalBroadcastEvent(World.onUpdate, (data) => { this.onUpdate(data.deltaTime); });
            // set the max and min values based on the entities position at world start and its set offsets
            this.maxPos = this.entity.position.get().add(new Vec3(this.props.xOffset, this.props.yOffset, this.props.zOffset));
            this.minPos = this.entity.position.get().sub(new Vec3(this.props.xOffset, this.props.yOffset, this.props.zOffset));
    
            this.ChangePosition();
        }
    
        onUpdate(deltaTime: number) {
            // we only want this to run if the object is supposed to be moving
            if (this.isMoving) {
                const currentTime = Date.now();
                this.elapsedTime = currentTime - this.startTime;
    
                // if the object has been moving longer than the desired amount of time
                if (this.elapsedTime >= this.duration) {
                    this.entity.position.set(this.targetPosition);
                    this.startPosition = this.entity.position.get();
                    this.isMoving = false;
                    this.elapsedTime = 0;
                    this.ChangePosition();
                }
                else {
                    let amount = (this.elapsedTime / this.duration) * deltaTime * this.props.moveSpeed;
                    this.startPosition = this.entity.position.get();
                    const currentPosition = Vec3.lerp(this.startPosition, this.targetPosition, amount);
                    this.entity.position.set(currentPosition);
    
                    // increase the amount for slerp so the object rotates faster than it moves
                    amount *= 10;
                    const startRot = this.entity.rotation.get();
                    const endRot = Quaternion.lookRotation(this.targetPosition.sub(this.entity.position.get()), this.entity.up.get());
                    this.entity.rotation.set(Quaternion.slerp(startRot, endRot, amount));
                }
            }
        }
    
        async ChangePosition() {
            // set our new x, y, and z values
            // NOTE: If both values are not negative or positive then it can give unwanted values
            const x = Math.random() * (this.maxPos.x - this.minPos.x);
            const y = Math.random() * (this.maxPos.y - this.minPos.y);
            const z = Math.random() * (this.maxPos.z - this.minPos.z);
    
            // set a new vector to the random x, y, and z values and set the entities position to the new vector
            this.startTime = Date.now()
            this.targetPosition = new Vec3(x, y, z);
            this.isMoving = true;
        }
    }
    Component.register(RandomMoveWithinArea);