繁体   English   中英

如何通过清单 <Interface> 和另一个类的实现方法

[英]How to pass a List<Interface> and an implemented method from another class

我有一个游戏管理器,它用于管理所有其他脚本中特定Unity回调( FixedUpdateUpdateLateUpdate )的执行顺序。

具体来说,我编写了以下3个接口:

public interface IFixedAt {
    bool IsActive { get; }
    void FixedAt(); 
}

public interface IUpdateAt {
    bool IsActive { get; }
    void UpdateAt();
}

public interface ILateUpdateAt {
    bool IsActive { get; }
    void LateUpdateAt();
}

这些接口在游戏对象的脚本中根据需要实现,例如:

using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour, IUpdateAt, ILateUpdateAt {

    [SerializeField]
    bool isActive = true;
    public bool IsActive {
        get {
            return (isActive && gameObject.activeInHierarchy);
        }
    }

    public void UpdateAt() {
        // Do stuff in Update
    }

    public void LateUpdateAt() {
        // Do stuff in Late Update
    }
}

Game Manager脚本在Awake处获得对所有实现接口的脚本的引用,创建一个List<Interface> ,然后在运行时使用该列表仅在需要时执行回调:

using UnityEngine;
using System.Collections.Generic;

public class GameManager : MonoBehaviour {

    public List<GameObject> GameObjectsWithScripts;
    List<IFixedAt> fixedAtList { get; set; }
    List<IUpdateAt> updateAtList { get; set; }
    List<ILateUpdateAt> lateUpdateAtList { get; set; }

    private void Awake() {
        PopulateAllLists();
    }

    private void FixedUpdate() {        
        if (fixedAtList != null) {
            for (int i = 0; i < fixedAtList.Count; i++) {
                if (fixedAtList[i].IsActive)
                    fixedAtList[i].FixedAt();
            }
        }
    }

    private void Update() {
        if (updateAtList != null) {
            for (int i = 0; i < updateAtList.Count; i++) {  
                if (updateAtList[i].IsActive)
                    updateAtList[i].UpdateAt();
            }
        }       
    }

    private void LateUpdate() {
        if (lateUpdateAtList != null) {
            for (int i = 0; i < lateUpdateAtList.Count; i++) {
                if (lateUpdateAtList[i].IsActive)
                    lateUpdateAtList[i].LateUpdateAt();
            }
        }
    }

    void PopulateAllLists() {
        fixedAtList = PopulateList<IFixedAt>(GameObjectsWithScripts);
        updateAtList = PopulateList<IUpdateAt>(GameObjectsWithScripts);
        lateUpdateAtList = PopulateList<ILateUpdateAt>(GameObjectsWithScripts);     
    }

    List<T> PopulateList<T> (List<GameObject> goScripts) {
        //Scans the GOs list and adds existent interface elements to the list
        var list = new List<T>();
        for (int i = 0; i < goScripts.Count; i++) {
            if (goScripts[i].GetComponent<T>() != null) {
                list.Add(goScripts[i].GetComponent<T>());               
            }           
        }

        //Returns list (null if list is empty)
        if (list.Count > 0) {
            return list;
        }
        else {
            return null;
        }
    }
}

现在,这个问题让我难以理解是否可以执行,如果可以,如何执行。

如您所见, FixedUpdateUpdateLateUpdate内部的代码基本相同:它在特定的List上进行迭代,检查当前元素是否处于活动状态,如果为true,则执行专有回调。

我想知道的是,是否有可能创建一个可以从三个回调内部调用的通用方法,并将要迭代的List传递给它,并调用该List的特定方法,在伪代码中类似这样:

private void FixedUpdate() {        
    Method (fixedAtList, FixedAt() );
}

private void Update() {        
    Method (updateAtList, UpdateAt() );
}

private void LateUpdate() {        
    Method (lateUpdateAtList, LateUpdateAt() );
}

private void Method<T> (List<T> list, Action method) {
    if (list != null) {
        for (int i = 0; i < list.Count; i++) {  
            if (list[i].IsActive)
                list[i].method();
        }
    }
}

我尝试了不同的方法,但都没有成功,而且atm对于如何做到这一点一无所知。 任何帮助将不胜感激。

首先,您需要一个涵盖IsActive方法的接口。

public interface IActive {
    bool IsActive { get; }
}

public interface IFixedAt : IActive {
    void FixedAt(); 
}

public interface IUpdateAt : IActive {
    void UpdateAt();
}

public interface ILateUpdateAt : IActive {
    void LateUpdateAt();
}

然后,您需要使用通用的Action<T> ,然后可以传入lambdas

private void FixedUpdate() {        
    Method (fixedAtList, f => f.FixedAt() );
}

private void Update() {        
    Method (updateAtList, u => u.UpdateAt() );
}

private void LateUpdate() {        
    Method (lateUpdateAtList, l => l.LateUpdateAt() );
}

private void Method<T> (List<T> list, Action<T> method) where T : IActive {
    if (list != null) {
        for (int i = 0; i < list.Count; i++) {  
            if (list[i].IsActive)
                method(list[i]);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM