U4S2SL3——数据带来的多态行为

数据带来的多态行为

某些行为的变化是因为数据的不同带来的,我们可以利用面向对象的特性和原则,以及设计模式相关知识点
结合ScriptableObject做出更加方便的功能

比如随机音效,物品拾取,AI等等等

  • 随机音效(里氏替换原则和依赖倒转原则)

    播放音乐时,可能会随机播放多个音效当中的一种

  • 物品拾取(里氏替换原则和依赖倒转原则)

    比如拾取一个物品,物品给玩家带来不同的效果

  • AI

    不同数据带来的不同行为模式

为了方便我们使用,我们可以利用ScriptableObject的可配置性来制作这些功能

其实下面的例子中的功能就算不用ScriptableObject也是能够用面向对象的思想,结合配置文件来完成的
但是ScriptableObject具备自己的几个优点

  1. 更方便的配置
  2. 共享数据节约内存

在实现某些功能的时候,使用ScriptableObject会更加方便我们的使用

举例说明

随机音效

1
2
3
4
5
6
using UnityEngine;

public abstract class AudioPlayBase : ScriptableObject
{
public abstract void Play(AudioSource source);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu()]
public class RandomPlayAudio : AudioPlayBase
{
//希望随机播放的音效文件
public List<AudioClip> clips;

public override void Play(AudioSource source)
{
if (clips.Count == 0)
return;
//设置音效切片文件
source.clip = clips[Random.Range(0, clips.Count)];
source.Play();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;

public class Lesson7 : MonoBehaviour
{
public AudioPlayBase audioPlay;

void Start()
{
audioPlay.Play(this.GetComponent<AudioSource>());
}
}

之后我们在Inspector窗口内设置随机播放的音效列表,即可实现随机播放音效

这里我们通过里氏替换原则来使Lesson7​用父类(AudioPlayBase)​装子类(RandomAudioPlay)
再通过依赖倒转原则使Lesson7​调用父类(AudioPlayBase)​的抽象方法(Play())​而实际执行子类(RandomAudioPlay)​的方法

再写一个正常的播放音效的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
using UnityEngine;

[CreateAssetMenu()]
public class PlayAudio : AudioPlayBase
{
public AudioClip clip;

public override void Play(AudioSource source)
{
source.clip = clip;
source.Play();
}
}

再让Lesson7​用父类(AudioPlayBase)​装子类(PlayAudio)​,调用父类(AudioPlayBase)​的抽象方法(Play())​而实际执行子类(AudioPlay)​的方法

这样Lesson7​在调用同样的Play()​时,根据子类的不同,执行不同的方法
这样就可以实现数据带来的多态行为

物品拾取

先实现一个抽象的物品效果类ItemEffect

1
2
3
4
5
6
using UnityEngine;

public abstract class ItemEffect : ScriptableObject
{
public abstract void AddEffect(GameObject obj);
}

再通过这个基类实现加攻击效果类AddAtkItemEffect​和加生命效果类AddHealthItemEffect

1
2
3
4
5
6
7
8
9
10
11
12
13
using UnityEngine;

[CreateAssetMenu()]
public class AddHealthItemEffect : ItemEffect
{
public int num;

public override void AddEffect(GameObject obj)
{
//通过获取到的对象,让其加血
//obj.GetComponent<...>().hp += num
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
using UnityEngine;

[CreateAssetMenu()]
public class AddAtkItemEffect : ItemEffect
{
public int num;

public override void AddEffect(GameObject obj)
{
//通过获取到的对象,让其攻击力
//obj.GetComponent<...>().atk += num
}
}

再实现一个物品对象类,里面有物品效果类ItemEffect​的成员变量

1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;

public class ItemObj : MonoBehaviour
{
public ItemEffect eff;

private void OnTriggerEnter(Collider other)
{
//为和物品产生碰撞的对象加效果
eff.AddEffect(other.gameObject);
}
}

接下来,就可以通过eff​变量关联的不同的ItemEffect​派生类生成的配置文件实现接触到ItemObj​对象碰撞盒的对象产生不同的效果