저의 목표는 다음과 같은 것을 처리 할 수있는 가능한 아이템 시스템을 가능한 한 모듈 식으로 만드는 것입니다
- 업그레이드 가능한 아이템 (+6 Katana)
- 능력치 수정 제 (+15 민첩)
- 아이템 수정 자 (% X 확률로 Y 데미지, 동결 확률)
- 충전식 (30 인용 매직 스태프)
- 항목 설정 (Y 기능을 활성화하기 위해 X 세트 4 장 세트)
- 희귀 성 (일반, 고유, 전설)
- 마력 추출 가능 (일부 제작 재료에 들어감)
- 제작 가능 (특정 재료로 제작 가능)
- 소모품 (5 분 % X 공격력, 치유 +15 HP)
* 다음 설정에서 굵게 표시된 기능을 해결할 수있었습니다.
이제 내가 생각한 것을 반영하기 위해 많은 옵션을 추가하려고했습니다. 필요한 모든 기능을 추가 할 계획은 없지만 적합하다고 생각되는대로 구현할 수 있기를 원합니다. 또한 인벤토리 시스템 및 데이터 직렬화와 호환되어야합니다.
상속 을 전혀 사용하지 않고 엔티티 구성 요소 / 데이터 기반 접근 방식을 계획하고 있습니다. 처음에는 다음과 같은 시스템을 생각했습니다.
- BaseStat : 이동 중에 통계를 보유하는 일반 클래스 (항목 및 캐릭터 통계에도 사용할 수 있음)
- Item : 목록, 이름, itemtype 및 ui, actionName, description 등과 관련된 것들과 같은 데이터를 보유하는 클래스입니다.
- 무기 : 무기 인터페이스. 모든 무기에는 IWeapon이 구현 된 자체 클래스가 있습니다. 여기에는 Attack 및 캐릭터 통계에 대한 참조가 있습니다. 무기가 장착되면 데이터 (아이템 클래스의 스탯)가 캐릭터 스탯에 주입됩니다. (베이스 스테이트가 무엇이든, 스탯 보너스로 캐릭터 클래스에 추가됩니다.) 예를 들어, 칼로 캐릭터 스탯에 5 번의 공격을가 합니다. 따라서 BaseStat 는 ( "Attack", 5) (enum도 사용할 수 있습니다)입니다. 이 스탯은 장착시 캐릭터의 "공격"스탯에 보너스 스탯 (다른 클래스)으로 추가됩니다. 따라서 Sword 라는 클래스는 IWeapon 을 구현할 때 생성됩니다.품목 클래스 가 생성됩니다. 따라서 우리는 이 검에 캐릭터 스탯 을 주입 할 수 있고, 공격 할 때 캐릭터 스탯 에서 총 어택 스탯을 가져 와서 공격 방법에 피해를 입힐 수 있습니다.
- BonusStat : BaseStat를 건드리지 않고 통계를 보너스로 추가하는 방법입니다.
- 소모품 : IWeapon과 동일한 논리. 다이렉트 스탯을 추가하는 것은 상당히 쉽지만 (+15 hp)이 설정으로 임시 무기를 추가할지는 확실하지 않습니다 (5 분 동안 공격 할 % x).
- 업그레이드 가능 :이 설정으로 구현할 수 있습니다. UpgradeLevel 을 기본 스탯으로 생각 하며 무기를 업그레이드하면 증가합니다. 업그레이드 할 때 무기의 BaseStat 를 업그레이드 수준에 맞게 다시 계산할 수 있습니다 .
이 시점까지 시스템이 상당히 좋다는 것을 알 수 있습니다. 그러나 다른 기능을 위해, 나는 예를 들어 내 나는이에 Craftable 기능을 구현 할 수 없기 때문에 우리가 뭔가를해야한다고 생각 BaseStat가 이 기능을 처리 할 수 없을 것 내가 붙어있어 곳입니다. 모든 재료를 스탯으로 추가 할 수 있지만 의미가 없습니다.
이를 쉽게 제공 할 수 있도록 다음과 같이 도움이 될만한 몇 가지 질문이 있습니다.
- 다른 기능을 구현하려면이 설정을 계속해야합니까? 상속없이 가능할까요?
- 상속없이 이러한 모든 기능을 구현하기 위해 생각할 수있는 방법이 있습니까?
- 아이템 수정 자에 대해서는 어떻게 달성 할 수 있습니까? 그것은 본질적으로 매우 일반적이기 때문에.
- 이런 종류의 아키텍처를 구축하는 과정, 권장 사항을 쉽게하기 위해 무엇을 할 수 있습니까?
- 이 문제와 관련하여 발굴 할 수있는 출처가 있습니까?
- 나는 상속을 피하려고 노력하지만 상속을 유지하면서 쉽게 유지하면서 쉽게 해결 / 달성 할 것이라고 생각합니까?
질문을 매우 넓게 유지하면서 여러 가지 측면 / 사람들로부터 지식을 얻을 수 있으므로 단 하나의 질문에 자유롭게 대답하십시오.
편집하다
@ jjimenezg93의 답변에 따라 테스트를 위해 C #에서 매우 기본적인 시스템을 만들었습니다. 추가 할 수 있는지 확인하십시오.
public interface IItem
{
List<IAttribute> Components { get; set; }
void ReceiveMessage<T>(T message);
}
public interface IAttribute
{
IItem source { get; set; }
void ReceiveMessage<T>(T message);
}
지금까지 IItem 및 IAttribute는 기본 인터페이스입니다. 메시지에 대한 기본 인터페이스 / 속성을 가질 필요가 없었으므로 테스트 메시지 클래스를 직접 만들 것입니다. 이제 테스트 수업 :
public class TestItem : IItem
{
private List<IAttribute> _components = new List<IAttribute>();
public List<IAttribute> Components
{
get
{
return _components;
}
set
{
_components = value;
}
}
public void ReceiveMessage<T>(T message)
{
foreach (IAttribute attribute in Components)
{
attribute.ReceiveMessage(message);
}
}
}
public class TestAttribute : IAttribute
{
string _infoRequiredFromMessage;
public TestAttribute(IItem source)
{
_source = source;
}
private IItem _source;
public IItem source
{
get
{
return _source;
}
set
{
_source = value;
}
}
public void ReceiveMessage<T>(T message)
{
TestMessage convertedMessage = message as TestMessage;
if (convertedMessage != null)
{
convertedMessage.Execute();
_infoRequiredFromMessage = convertedMessage._particularInformationThatNeedsToBePassed;
Debug.Log("Message passed : " + _infoRequiredFromMessage);
}
}
}
public class TestMessage
{
private string _messageString;
private int _messageInt;
public string _particularInformationThatNeedsToBePassed;
public TestMessage(string messageString, int messageInt, string particularInformationThatNeedsToBePassed)
{
_messageString = messageString;
_messageInt = messageInt;
_particularInformationThatNeedsToBePassed = particularInformationThatNeedsToBePassed;
}
//messages should not have methods, so this is here for fun and testing.
public void Execute()
{
Debug.Log("Desired Execution Method: \nThis is test message : " + _messageString + "\nThis is test int : " + _messageInt);
}
}
필요한 설정입니다. 이제 우리는 시스템을 사용할 수 있습니다 (다음은 Unity 용입니다).
public class TestManager : MonoBehaviour
{
// Use this for initialization
void Start()
{
TestItem testItem = new TestItem();
TestAttribute testAttribute = new TestAttribute(testItem);
testItem.Components.Add(testAttribute);
TestMessage testMessage = new TestMessage("my test message", 1, "VERYIMPORTANTINFO");
testItem.ReceiveMessage(testMessage);
}
}
이 TestManager 스크립트를 장면의 컴포넌트에 첨부하면 디버그에서 메시지가 성공적으로 전달되었음을 알 수 있습니다.
설명하기 위해 : 게임의 모든 항목은 IItem 인터페이스를 구현하고 모든 속성 (이름은 당신을 혼동해서는 안됩니다. 항목 기능 / 시스템을 의미합니다. 그런 다음 메시지를 처리하는 방법이 있습니다 (메시지가 필요한 이유는 추가 예에서 설명 함). 따라서 문맥에 따라 항목에 속성을 첨부하고 나머지는 자동으로 수행 할 수 있습니다. 속성을 쉽게 추가 / 제거 할 수 있기 때문에 매우 유연합니다. 따라서 의사 예제는 마력을 잃을 수 있습니다. Disenchantable (IAttribute)라는 클래스가 있으며 Disenchant 메서드에서 다음을 요청합니다.
- 재료 나열 (아이템이 마력을 잃었을 때, 플레이어에게 어떤 아이템을 주어야 하는가) 참고 : IItem은 ItemType, ItemID 등을 갖도록 확장되어야합니다.
- int resultModifier (만약 당신이 마력 제거 기능을 강화하면, 마력을 잃었을 때받은 재료를 증가시키기 위해 int를 전달할 수 있습니다)
- int failureChance (마법 해제 프로세스에 실패 확률이있는 경우)
기타
이 정보는 DisenchantManager라는 클래스에 의해 제공되며, 아이템을 받고 아이템 (마법 해제시 아이템의 성분)과 플레이어 진행 (resultModifier 및 failureChance)에 따라이 메시지를 형성합니다. 이 메시지를 전달하기 위해이 메시지의 본문 역할을하는 DisenchantMessage 클래스를 만듭니다. 따라서 DisenchantManager는 DisenchantMessage를 채우고 항목으로 보냅니다. 아이템은 메시지를 받아서 첨부 된 모든 속성에 전달합니다. Disenchantable 클래스의 ReceiveMessage 메서드는 DisenchantMessage를 찾기 때문에 Disenchant 특성 만이 메시지를 수신하고 그에 따라 작동합니다. 이것이 나를 위해했던 것처럼 많은 일을 해결하기를 바랍니다 :).