Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Search Gists
Sign in Sign up

Instantly share code, notes, and snippets.

@adammyhre
CreatedMay 25, 2025 10:34
    • Star(8)You must be signed in to star a gist
    • Fork(1)You must be signed in to fork a gist

    Select an option

    Save adammyhre/8e6f57d24e96d33738273ed0570828be to your computer and use it in GitHub Desktop.
    Modular Ability Effects
    usingSystem;
    usingSystem.Collections.Generic;
    usingUnityEngine;
    [CreateAssetMenu(fileName="AbilityData",menuName="ScriptableObjects/AbilityData")]
    classAbilityData:ScriptableObject{
    publicstringlabel;
    publicAnimationClipanimationClip;
    [Range(0.1f,4f)]publicfloatcastTime=2f;
    publicProjectileMovevfxPrefab;
    [SerializeReference]publicList<AbilityEffect>effects;
    voidOnEnable(){
    if(string.IsNullOrEmpty(label))label=name;
    if(effects==null)effects=newList<AbilityEffect>();
    }
    }
    [Serializable]
    abstractclassAbilityEffect{
    publicabstractvoidExecute(GameObjectcaster,GameObjecttarget);
    }
    [Serializable]
    classDamageEffect:AbilityEffect{
    publicintamount;
    publicoverridevoidExecute(GameObjectcaster,GameObjecttarget){
    target.GetComponent<Health>().ApplyDamage(amount);
    Debug.Log($"{caster.name} dealt{amount} damage to{target.name}");
    }
    }
    [Serializable]
    classKnockbackEffect:AbilityEffect{
    publicfloatforce;
    publicoverridevoidExecute(GameObjectcaster,GameObjecttarget){
    vardir=(target.transform.position-caster.transform.position).normalized;
    target.GetComponent<Rigidbody>().AddForce(dir*force,ForceMode.Impulse);
    Debug.Log($"{caster.name} knocked back{target.name} with force{force}");
    }
    }
    usingUnityEngine;
    usingUnityEditor;
    usingSystem;
    usingSystem.Linq;
    usingSystem.Collections.Generic;
    [CustomPropertyDrawer(typeof(AbilityEffect),true)]
    publicclassAbilityEffectDrawer:PropertyDrawer{
    staticDictionary<string,Type>typeMap;
    publicoverridevoidOnGUI(Rectposition,SerializedPropertyproperty,GUIContentlabel){
    if(typeMap==null)BuildTypeMap();
    vartypeRect=newRect(position.x,position.y,position.width,EditorGUIUtility.singleLineHeight);
    varcontentRect=newRect(position.x,position.y+EditorGUIUtility.singleLineHeight,position.width,position.height-EditorGUIUtility.singleLineHeight);
    EditorGUI.BeginProperty(position,label,property);
    vartypeName=property.managedReferenceFullTypename;
    vardisplayName=GetShortTypeName(typeName);
    if(EditorGUI.DropdownButton(typeRect,newGUIContent(displayName??"Select Effect Type"),FocusType.Keyboard)){
    varmenu=newGenericMenu();
    if(typeMap==null||typeMap.Count==0){
    menu.AddDisabledItem(newGUIContent("No Ability Effects available"));
    menu.ShowAsContext();
    return;
    }
    foreach(varkvpintypeMap){
    varname=kvp.Key;
    vartype=kvp.Value;
    menu.AddItem(newGUIContent(name),type.FullName==typeName,()=>{
    property.managedReferenceValue=Activator.CreateInstance(type);
    property.serializedObject.ApplyModifiedProperties();
    });
    }
    menu.ShowAsContext();
    }
    if(property.managedReferenceValue!=null){
    EditorGUI.indentLevel++;
    EditorGUI.PropertyField(contentRect,property,GUIContent.none,true);
    EditorGUI.indentLevel--;
    }
    EditorGUI.EndProperty();
    }
    publicoverridefloatGetPropertyHeight(SerializedPropertyproperty,GUIContentlabel){
    returnEditorGUI.GetPropertyHeight(property,label,true)+EditorGUIUtility.singleLineHeight;
    }
    staticvoidBuildTypeMap(){
    varbaseType=typeof(AbilityEffect);
    typeMap=AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(asm=>{
    try{returnasm.GetTypes();}
    catch{returnType.EmptyTypes;}
    })
    .Where(t=>!t.IsAbstract&&baseType.IsAssignableFrom(t))
    .ToDictionary(t=>ObjectNames.NicifyVariableName(t.Name), t=>t);
    }
    staticstringGetShortTypeName(stringfullTypeName){
    if(string.IsNullOrEmpty(fullTypeName))returnnull;
    varparts=fullTypeName.Split(' ');
    returnparts.Length>1?parts[1].Split('.').Last():fullTypeName;
    }
    }
    usingSystem.Collections;
    usingUnityEngine;
    usingUnityEngine.InputSystem;
    usingAdvancedController;
    usingImprovedTimers;
    classAbilityExecutor:MonoBehaviour{
    [SerializeField]AbilityDataability;
    [SerializeField]GameObjecttarget;
    AnimationControlleranimationController;
    CountdownTimercastTimer;
    voidAwake(){
    animationController=GetComponent<AnimationController>();
    castTimer=newCountdownTimer(ability.castTime);
    castTimer.OnTimerStart=()=>animationController.OrNull()?.PlayOneShot(ability.animationClip);
    castTimer.OnTimerStop=()=>SpawnVFX();
    }
    voidSpawnVFX(){
    if(ability.vfxPrefab==null)return;
    varvfx=Instantiate(ability.vfxPrefab,transform.position,transform.rotation);
    vfx.SetCallback((Collisionco)=>{
    foreach(vareffectinability.effects){
    effect.Execute(gameObject,target);
    }
    });
    Destroy(vfx,5f);
    }
    publicvoidExecute(GameObjecttarget){
    castTimer.Start();
    }
    voidUpdate(){
    if(Keyboard.current.spaceKey.wasPressedThisFrame){
    Execute(target);
    }
    }
    }
    Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

    [8]ページ先頭

    ©2009-2025 Movatter.jp