Turning a static code into dynamic code

 if (app.keyboard.wasPressed(pc.KEY_1) && this.arms.anim.baseLayer.activeState !== 'Pistol idle') {
        this.switchWeapons(0);
        this.switchWeaponIcons(0);
        this.arms.anim.setBoolean('pistol idle', true);
        this.arms.anim.setBoolean('rifle idle', false);
    }

    if (app.keyboard.wasPressed(pc.KEY_2) && this.arms.anim.baseLayer.activeState !== 'Rifle idle') {
        this.switchWeapons(1);
        this.switchWeaponIcons(1);
        this.arms.anim.setBoolean('rifle idle', true);
        this.arms.anim.setBoolean('pistol idle', false);
    }

Hello, i was asked to turn the above code, specifically the part which changes the arms animation into dynamic code. To be more clear, ā€œthis.arms.anim.baseLayer.activeState !== ā€˜Pistol idleā€™)ā€ there shouldnā€™t be the name of animations. I understand that there need to be a for loop for the animation states just like i did with the weapon models and icons. But i donā€™t know how i can set bools in the if statement without writing animation names. I canā€™t figure out what to do, iā€™d appreciate any tips and pointers regarding this issue

@Ronin This is just a thought on how to accomplish this but probably not ideal. What you could do is create an animation state graph with transitions to each state. Each state would be changed by a number and not a name. This will work but the down fall is number one you will have to keep all the numbers referencing states correct as you replace. The other downside would be that your code would not be very readable to others since others would have to refence the state graph parameter to figure out what is happening. Hope this helps. I am sure others will chime in if more ideas come to mind.

my supervisor doesnā€™t want anything in the script to be hardcoded, thatā€™s the thing. But i donā€™t understand how i can switch animations without calling their name. This is his exact instructions:

For example, we should not have movement code in the weaponManager or do static controls like this.arms.anim.baseLayer.activeState !== ā€˜Rifle reloadā€™ instead, we should be able to check activeState == reload and set the current weapon with the weaponType value.

We should be able to check activeState == reload and set the current weapon with the weaponType value.*
If you write the animation names as weaponType + ā€˜-Reloadā€™ it will be dynamic

@Ronin The best I can tell from the snippet above is that there is a decision being made as to if the animation state is not already in the state you want to switch it to. This is logical as you donā€™t need to switch the animation if it is already in that state. I understand the question about the naming. I really donā€™t know how you can make it more generic other than just using numbers or something. You could keep an object array of containing each weapon which would include attributes or maybe JSON structure that could be used to pull generic tags from for the names.

2 Likes

I think the goal is to use for example one variable for your weapon and use this variable in your code to switch to the correct weapon and animation. This way your code is dynamic because you donā€™t have to add a lot of code if you add for example a new weapon. No idea if Iā€™m correct.

2 Likes

Thanks for all the input you offered. I guess iā€™m not the only one who couldnā€™t understand what my supervisor is asking from me exactly. I also asked my brother who is a programmer for help, his solution wasnā€™t also what my supervisor wanted to achieve. We decided to skip that part for now, i return here if thereā€™ll be any changes. Thanks a million again

1 Like

Probably wants you to use a scripts attribute and have it data driven through the Editor instead

yes i understood that but couldnā€™t figure out how to execute it in this case.

I used this code to switch the animations with a for loop, he said this in response:

This is the issue Iā€™m talking about, you canā€™t do this with index etc. when the order of those weapons is changed then you will need to fix the code again

Ah, I think I know what he is getting at now. What is this.weapons? An array of JSON?

yes

WeaponManager.attributes.add('weapons', { type: 'entity', array: true });

There are a copy of ways to do this but they all roughly amount to the same thing which is to create a data structure where you can reference by name.

this.weapons and this.weaponIcons are closely related, use a JSON attribute so that they are mapped together instead of separate arrays.

https://developer.playcanvas.com/en/user-manual/scripting/script-attributes/#json-attribute

So your this.weapons attribute will become like this (untested):

WeaponManager.attributes.add('weapons', {
    type: 'json',
    array: true,
    schema: [{
        name: 'name',
        type: 'string'
    }, {
        name: 'worldEntity',
        type: 'entity'
    }, {
        name: 'iconEntity',
        type: 'entity'
    }]
});

And then you can find it by name instead (untested):

WeaponManager.prototype.switchWeapons = function(name) {
    let chosenWeapon = null;
    for (let i = 0; i < this.weapons.length; i++) {
        const weapon = this.weapons[i];
        weapon.worldEntity.enabled = false;
        weapon.iconEntity.enabled = false;
        this.arms.setBoolean(weapon.name + ' idle', false);

        if (weapon.name === name) {
            chosenWeapon = weapon;
        }
    }

    if (chosenWeapon) {
        chosenWeapon.worldEntity.enabled = true;
        chosenWeapon.iconEntity.enabled = true;
        this.arms.setBoolean(chosenWeapon.name + ' idle', true);
    } else {
        console.error("Can't find chosen weapon: " + name);
    }
};
3 Likes

thx a lot for your time. Iā€™ll try this as soon as i have the time