如何从另一个类传递List <interface>和实现的方法

时间:2017-07-02 19:17:40

标签: c# unity3d parameters interface

我有一个游戏管理器,用于管理所有其他脚本中特定Unity回调(UpdateLateUpdatepublic 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
    }
}

这些界面在游戏对象中实现。脚本,如果需要,例如:

List<Interface>

游戏管理器脚本获取Awake对实现接口的所有脚本的引用,创建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; } } } 然后在运行时使用列表仅在需要时执行回调:

FixedUpdate

现在,我无法理解是否有可能做到的问题,如果可以的话,该怎么做。

如您所见,UpdateLateUpdateList中的代码基本相同:它在特定List上进行迭代,检查当前元素是否为active,如果为true,则执行专有回调。

我想知道的是,是否可以创建一个可以从三个回调中调用的泛型方法,并向其传递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(); } } } ,在伪代码中是这样的:

getEmployeeCredits(id) {
            if (this.state.company_roles) {
                return this.state.company_roles.map(function (cr, i) {
                    if (cr.id  === id) {
                        return cr.assigned_credits
                    }
                    else 
                       return undefined;
                }.bind(this));
            }
        }

我尝试了不同的事情,但没有成功,而且我对如何做到这一点毫无头绪。任何帮助将非常感激。

1 个答案:

答案 0 :(得分:3)

首先,您需要一个涵盖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]);
        }
    }
}