একটি উপাদান ভিত্তিক সত্তা সিস্টেমের জন্য কী ডিজাইন রয়েছে যা ব্যবহারকারীর পক্ষে বন্ধুত্বপূর্ণ তবে এখনও নমনীয়?


23

আমি কিছুক্ষণের জন্য উপাদান ভিত্তিক সত্তা সিস্টেমে আগ্রহী হয়েছি এবং এতে অজস্র নিবন্ধগুলি পড়েছি (দ্য ইনসোমিয়াক গেমস , দুর্দান্ত মানটি আপনার হায়ারার্কি টি , টি-মেশিন , ক্রোনোক্লাস্ট ... মাত্র কয়েকটি নাম দেওয়ার জন্য)।

তাদের সকলেরই এমন কোনও কিছুর বাইরের কাঠামো রয়েছে বলে মনে হয়:

Entity e = Entity.Create();
e.AddComponent(RenderComponent, ...);
//do lots of stuff
e.GetComponent<PositionComponent>(...).SetPos(4, 5, 6);

এবং যদি আপনি ভাগ করা ডেটা সম্পর্কে ধারণা নিয়ে আসেন (এটি এখন পর্যন্ত আমি দেখেছি সেরা ডিজাইন, কোথাও তথ্য নকল না করার শর্তে)

e.GetProperty<string>("Name").Value = "blah";

হ্যাঁ, এটি খুব দক্ষ। যাইহোক, এটি পড়া বা লেখার পক্ষে ঠিক সহজ নয়; এটি আপনার কাছে খুব চতুর এবং পরিশ্রমী বোধ করে।

আমি ব্যক্তিগতভাবে কিছু করতে চাই:

e.SetPosition(4, 5, 6);
e.Name = "Blah";

যদিও অবশ্যই এই ধরণের ডিজাইনের কাছে আসার একমাত্র উপায় হ'ল সত্তা-> এনপিসি-> শত্রু-> ফ্লাইংএনেমি-> ফ্লাইংএনেমি উইথাহাট এক ধরণের শ্রেণিবদ্ধতা এড়াতে চেষ্টা করে।

কেউ কি এই ধরণের উপাদান উপাদানগুলির জন্য এমন কোনও নকশা দেখেছেন যা এখনও নমনীয়, তবুও ব্যবহারকারী বন্ধুত্বের একটি স্তর বজায় রাখে? এবং এই বিষয়টির জন্য, (সম্ভবত সবচেয়ে কঠিন সমস্যা) একটি ভাল উপায়ে ডেটা স্টোরেজটি পেতে পারেন?

একটি উপাদান ভিত্তিক সত্তা সিস্টেমের জন্য কী ডিজাইন রয়েছে যা ব্যবহারকারীর পক্ষে বন্ধুত্বপূর্ণ তবে এখনও নমনীয়?

উত্তর:


13

ইউনিটি যা করে তার মধ্যে একটি হ'ল সাধারণ উপাদানগুলিতে আরও বেশি ব্যবহারকারী বান্ধব অ্যাক্সেস সরবরাহ করতে পিতামাতার গেম অবজেক্টে কিছু সহায়ক সহায়িকা সরবরাহকারী।

উদাহরণস্বরূপ, আপনার ট্রান্সফর্ম উপাদানটিতে আপনার অবস্থান সঞ্চিত থাকতে পারে। আপনার উদাহরণ ব্যবহার করে আপনাকে এমন কিছু লিখতে হবে

e.GetComponent<Transform>().position = new Vector3( whatever );

কিন্তু ityক্যে, এটি সহজ হয়ে যায়

e.transform.position = ....;

transformআক্ষরিক অর্থে যেখানে বেস GameObjectক্লাসে কেবলমাত্র একটি সহজ সহায়ক পদ্ধতি ( Entityআপনার ক্ষেত্রে শ্রেণি) যা করে

Transform transform
{ 
    get { return this.GetComponent<Transform>(); }
}

Ityক্যটি আরও কয়েকটি কাজ করে, যেমন গেমের উপর "নাম" সম্পত্তি সেট করা যেমন তার সন্তানের উপাদানগুলির পরিবর্তে object

ব্যক্তিগতভাবে আমি আপনার ভাগ করা ডেটা বাই নাম ডিজাইনের ধারণা পছন্দ করি না। নামে পরিবর্তে একটি পরিবর্তনশীল দ্বারা বৈশিষ্ট্য অ্যাক্সেস করা এবং ব্যবহারকারী থাকার এছাড়াও কি এটা ঠিক সত্যিই আমাকে প্রবণ ত্রুটি মনে হয় টাইপ জানতে হবে। ইউনিটি যা করে তা হ'ল তারা ভাইবোনের উপাদানগুলি অ্যাক্সেস GameObject transformকরার জন্য Componentক্লাসের মধ্যে সম্পত্তি হিসাবে একই পদ্ধতি ব্যবহার করে । সুতরাং আপনার লেখার যেকোন স্বেচ্ছাসেবী উপাদান কেবল এটি করতে পারে:

var myPos = this.transform.position;

অবস্থান অ্যাক্সেস করতে। যেখানে transformসম্পত্তিটি এই জাতীয় কিছু করে

Transform transform
{
    get { return this.gameObject.GetComponent<Transform>(); }
}

অবশ্যই, এটি কেবল বলার চেয়ে কিছুটা ভারবস e.position = whatever, তবে আপনি এটিতে অভ্যস্ত হয়ে যান এবং এটি জেনেরিক বৈশিষ্ট্যগুলির মতো খারাপ লাগে না। এবং হ্যাঁ, আপনার ক্লায়েন্টের উপাদানগুলির জন্য আপনাকে এটি করতে হবে, তবে ধারণাটি হ'ল আপনার সমস্ত সাধারণ "ইঞ্জিন" উপাদান (রেন্ডারার্স, কলসিডারস, অডিও উত্সগুলি, ট্রান্সফর্মস ইত্যাদি) সহজেই অ্যাক্সেসর রয়েছে।


আমি দেখতে পাচ্ছি কেন ভাগ করা ডেটা-বাই-নাম সিস্টেমটি একটি সমস্যা হতে পারে তবে আমি কীভাবে একাধিক উপাদানগুলির ডেটার প্রয়োজনের সমস্যাটি এড়াতে পারি (উদাহরণস্বরূপ আমি কোনটিতে কিছু সঞ্চয় করি)? ডিজাইন পর্যায়ে কি খুব যত্নশীল?
কমিউনিস্ট হাঁস

এছাড়াও, 'ব্যবহারকারীর ধারণক্ষমতার ক্ষেত্রে এটি কী ধরণের তাও জানতে হবে', আমি কি এটি কেবল সম্পত্তিতে কাস্ট করতে পারি না? গেটটাইপ () গেট () পদ্ধতিতে পাবেন?
কম্যুনিস্ট হাঁস

1
আপনি কীভাবে বিশ্বব্যাপী (সত্তার সুযোগে) ডেটা এই ভাগ করা ডেটা সংগ্রহস্থলের দিকে চাপ দিচ্ছেন? যে কোনও ধরণের গেম অবজেক্ট ডেটা আপনার "ইঞ্জিন" ক্লাসগুলির মাধ্যমে (ট্রান্সফর্ম, কলসিডারস, রেন্ডার্স ইত্যাদি) সহজেই অ্যাক্সেসযোগ্য হওয়া উচিত। আপনি যদি এই "ভাগ করা ডেটা" এর উপর ভিত্তি করে গেমের যুক্তি পরিবর্তন করে থাকেন তবে এক শ্রেণীর নিজস্ব থাকা এবং এটি নিশ্চিত করা যায় যে কিছু নামক ভেরিয়েবল রয়েছে কিনা তা অন্ধভাবে জিজ্ঞাসা করার চেয়ে নিশ্চিত করে নিন যে সেই উপাদানটি সেই গেমের অবজেক্টে রয়েছে কিনা। সুতরাং হ্যাঁ, আপনি নকশা পর্যায়ে এটি হ্যান্ডেল করা উচিত। আপনি যদি প্রয়োজন হয় তবে আপনি সর্বদা এমন একটি উপাদান তৈরি করতে পারেন যা কেবলমাত্র ডেটা সঞ্চয় করে।
টেট্রাড

@ টেট্র্যাড - আপনি কীভাবে আপনার প্রস্তাবিত গেটকম্পোনেন্ট <ট্রান্সফর্ম> পদ্ধতিটি কাজ করবে তা সংক্ষিপ্তভাবে ব্যাখ্যা করতে পারেন? এটি কি গেমওজেক্টের সমস্ত উপাদানকে ফাঁকা করে টি টাইপের প্রথম উপাদানটি ফেরত দেবে? নাকি সেখানে অন্য কিছু চলছে?
মাইকেল

@ মিশেল যে কাজ করবে। পারফরম্যান্স উন্নতি হিসাবে স্থানীয়ভাবে তা ক্যাশে করা আপনি কলারের দায়িত্ব হিসাবে তৈরি করতে পারেন।
টেট্রাড

3

আপনার সত্তা অবজেক্টগুলির জন্য আমি এক ধরণের ইন্টারফেস ক্লাসটি সুপারিশ করব। কোনও সত্তায় যথাযথ মানের একটি উপাদান পাশাপাশি একই স্থানে রয়েছে তা নিশ্চিত করে পরীক্ষা করে এটি ত্রুটি পরিচালনা করতে পারে যাতে আপনি যে কোনও জায়গাতেই মানগুলিতে অ্যাক্সেস করতে পারেন না। পর্যায়ক্রমে, আমি উপাদানগুলি ভিত্তিক সিস্টেমের সাথে বেশিরভাগ ডিজাইন করেছি, আমি সরাসরি উপাদানগুলির সাথে কাজ করি, উদাহরণস্বরূপ, তাদের অবস্থানগত উপাদান এবং তারপরে সরাসরি সেই উপাদানটির বৈশিষ্ট্যগুলিতে অ্যাক্সেস / আপডেট করে।

উচ্চ স্তরে খুব বেসিক, শ্রেণিটি প্রশ্নে সত্তা গ্রহণ করে এবং অন্তর্নিহিত উপাদানগুলির অংশগুলিতে সহজেই ব্যবহারযোগ্য ইন্টারফেস সরবরাহ করে:

public class EntityInterface
{
    private Entity entity { get; set };
    public EntityInterface(Entity e)
    {
        entity = e;
    }

    public Vector3 Position
    {
        get
        {
            return entity.GetProperty<Vector3>("Position");
        }
        set
        {
            entity.GetProperty<Vector3>("Position") = value;
        }
    }
}

যদি আমি ধরে নিই যে আমাকে নোপজিশন কম্পোনেন্ট এক্সেকশন বা অন্য কোনও কিছুর জন্য হ্যান্ডেল করতে হবে, তবে এত্তের ক্লাসে কেবল সমস্ত কিছু রেখে দেওয়ার সুবিধা কী?
কম্যুনিস্ট হাঁস

আপনার সত্তা শ্রেণিতে আসলে কী আছে তা সম্পর্কে নিশ্চিত হওয়াতে আমি বলতে পারি না এর সুবিধা আছে কি না। আমি ব্যক্তিগতভাবে এমন উপাদান সিস্টেমগুলির পক্ষে পরামর্শ দিই যেখানে 'এর মধ্যে কী আছে' এর প্রশ্ন এড়াতে কেবল প্রতি-ভিত্তিতে কোনও বেস সত্তা নেই। তবে আমি এটির জন্য একটি ইন্টারফেস শ্রেণি হিসাবে এটি একটি ভাল যুক্তি বিবেচনা করব।
জেমস

আমি দেখতে পাচ্ছি যে এটি কীভাবে সহজ (আমাকে getProperty এর মাধ্যমে অবস্থান সম্পর্কে জিজ্ঞাসা করতে হবে না), তবে এটি সত্তা শ্রেণীর মধ্যে রাখার পরিবর্তে আমি এই উপকারটি দেখতে পাচ্ছি না।
কম্যুনিস্ট হাঁস

2

পাইথনে আপনি সত্তার উপর e.SetPosition(4,5,6)কোনও __getattr__ফাংশন ঘোষণার মাধ্যমে 'সেটপজিশন' অংশটি আটকাতে পারেন । এই ফাংশনটি উপাদানগুলির মাধ্যমে পুনরাবৃত্তি করতে পারে এবং উপযুক্ত পদ্ধতি বা সম্পত্তি খুঁজে পেতে এবং এটিটি ফিরিয়ে দিতে পারে, যাতে ফাংশন কল বা অ্যাসাইনমেন্ট সঠিক জায়গায় যায়। সম্ভবত সি # এর একটি একই সিস্টেম রয়েছে, তবে এটি স্ট্যাটিকালি টাইপ হওয়ার কারণে এটি সম্ভবত সম্ভব না - এটি সম্ভবত সংকলন করতে পারে না e.setPositionযদি না কোনও জায়গায় ইন্টারফেসে ই-পজিশন থাকে has

আপনি সম্ভবত আপনার সমস্ত সত্তা যে সমস্ত উপাদানগুলির সাথে যুক্ত করতে পারেন তার জন্য প্রাসঙ্গিক ইন্টারফেসগুলি প্রয়োগ করতে পারে, এমন একটি স্টাব পদ্ধতি যা একটি ব্যতিক্রম বাড়ায়। তারপরে আপনি যখন অ্যাডকোম্পোনেন্টকে কল করবেন, আপনি কেবলমাত্র উপাদানটির ইন্টারফেসের জন্য সত্তার ফাংশনগুলিকে উপাদানটিতে পুনঃনির্দেশ করুন। কিছুটা ম্লানভাবে যদিও।

কিন্তু সম্ভবত সবচেয়ে সহজ পদ্ধিতি হল, একটি বৈধ সম্পত্তি উপস্থিতি সংযুক্ত উপাদান অনুসন্ধান ও আসতে যে আপনার সত্তা বর্গ উপর [] অপারেটর জমিদার তাই এটা এত পছন্দ নির্ধারিত করা যেতে পারে হবে: e["Name"] = "blah"। প্রতিটি উপাদানকে তার নিজস্ব গেটপ্রোপার্টিবাইনেম বাস্তবায়ন করতে হবে এবং সত্তা যতক্ষণ না প্রশ্নে সম্পত্তিটির জন্য দায়ী উপাদানটি আবিষ্কার করে ততক্ষণ সত্ত্বাকে প্রত্যেকে কল করে।


আমি সূচকগুলি ব্যবহার করার কথা ভেবেছিলাম..এটি সত্যিই দুর্দান্ত। আর কী ঘটেছিল তা দেখার জন্য আমি কিছুটা অপেক্ষা করব, তবে আমি এর মিশ্রণের দিকে ঝুঁকছি, সাধারণ গেটকম্পোনেন্ট () এবং সাধারণ উপাদানগুলির জন্য প্রস্তাবিত @ জেমসের মতো কিছু বৈশিষ্ট্য।
কম্যুনিস্ট হাঁস

আমি এখানে যা বলছি তা অনুপস্থিত হতে পারে তবে এটি e.GetProperty <টাইপ> ("NameOfProperty") এর প্রতিস্থাপনের চেয়ে বেশি মনে হয় e ই ["NameOfProperty"] এর সাথে যাই হোক না কেন ??
জেমস

@ জেমস এটির জন্য একটি মোড়ক (এটি আপনার নকশার মতো অনেক বেশি) .. এটি আরও গতিময় - এটি স্বয়ংক্রিয়ভাবে এবং GetPropertyপদ্ধতির চেয়ে পরিষ্কার পরিচ্ছন্ন করে তোলে ... কেবলমাত্র নেতিবাচক দিকটি স্ট্রিংয়ের হেরফের এবং তুলনা। তবে এটি একটি মূল বিষয়।
কম্যুনিস্ট হাঁস

আহ, আমার ভুল বোঝাবুঝি সেখানে। আমি ধরে নিয়েছি যে getProperty সত্তার অংশ ছিল (এবং তাই উপরে বর্ণিত যা করত) তা নয় # সি পদ্ধতিটি।
জেমস

2

যদি আপনি C # এর 4.0 ব্যবহার করছেন Kylotan এর উত্তরে প্রসারিত করতে, আপনি স্ট্যাটিক্যালি একটি পরিবর্তনশীল টাইপ করা করতে পারেন গতিশীল

আপনি যদি সিস্টেম.ডায়নামিক.ডায়নামিক ওজেক্ট থেকে উত্তরাধিকারী হন তবে আপনি উপাদানগুলির নাম আটকাতে এবং অনুরোধকৃত উপাদানটি ফিরে পেতে ট্রাইগেটেমবার এবং ট্রাইসেটমেমারকে (বহু ভার্চুয়াল পদ্ধতির মধ্যে) ওভাররাইড করতে পারেন।

dynamic entity = EntityRegistry.Entities[1000];
entity.MyComponent.MyValue = 100;

আমি কয়েক বছর ধরে সত্তা সিস্টেমগুলি সম্পর্কে কিছুটা লিখেছি, তবে আমি ধরে নিয়েছি যে আমি দৈত্যগুলির সাথে প্রতিযোগিতা করতে পারি না। কিছু ইএস নোট (কিছুটা পুরানো এবং অগত্যা সত্তা সিস্টেমগুলি সম্পর্কে আমার বর্তমান বোঝার প্রতিফলন করে না, তবে এটি পড়ার পক্ষে মূল্যহীন)।


তার জন্য ধন্যবাদ, সাহায্য করবে :) গতিশীল উপায়ের কেবল সম্পত্তি হিসাবে ingালাইয়ের মতো একই ধরণের প্রভাব পড়বে না? যদিও গেটটাইপ (), তবে?
কম্যুনিস্ট হাঁস

ট্রাইগেমেম্বারের একটি আউট objectপ্যারামিটার রয়েছে বলে কোনও এক সময় কাস্ট হবে but তবে রানটাইমে এগুলি সব সমাধান করা হবে। আমি মনে করি এটি যেমন অস্তিত্বের উপরে একটি সাবলীল ইন্টারফেস রাখার একটি গৌরবময় উপায় T ট্রাইগেটকম্পোনেন্ট (কম্পোনাম, আউট উপাদান)) তবে আমি নিশ্চিত না যে আমি প্রশ্নটি বুঝতে পেরেছি :)
রাইন

প্রশ্নটি হ'ল আমি সর্বত্র গতিশীল ধরণ বা (এএএএফআইএস) ব্যবহার (সম্পত্তি.GetType ()) সম্পত্তি ব্যবহার করতে পারি।
কম্যুনিস্ট হাঁস

1

আমি এখানে সি # তে ইএসে প্রচুর আগ্রহ দেখছি। এটি চমৎকার ইএস বাস্তবায়ন আর্টেমিসের আমার বন্দরটি পরীক্ষা করে দেখুন:

https://github.com/thelinuxlich/artemis_CSharp

এছাড়াও, এটি কীভাবে কাজ করে তা শুরু করার জন্য একটি উদাহরণ গেম (এক্সএনএ 4 ব্যবহার করে): https://github.com/t ینوuxlich/starwarrior_CSharp

পরামর্শ স্বাগত!


অবশ্যই দেখতে সুন্দর লাগছে। আমি ব্যক্তিগতভাবে এতগুলি এনটিপিপ্রসেসিং সিস্টেমের ধারণার অনুরাগী নই - কোডে, ব্যবহারের ক্ষেত্রে এটি কীভাবে কার্যকর হয়?
কমিউনিস্ট হাঁস

প্রতিটি সিস্টেম এমন একটি দিক যা তার নির্ভরশীল উপাদানগুলি প্রক্রিয়া করে। ধারণাটি পেতে এটি দেখুন: github.com/tinnuxlich/starwarrior_CSharp/tree/master/…
thelinuxlich

0

আমি সি # এর দুর্দান্ত প্রতিবিম্ব সিস্টেমটি ব্যবহার করার সিদ্ধান্ত নিয়েছি। আমি এটিকে সাধারণ উপাদান সিস্টেমটি, পাশাপাশি উত্তরগুলির মিশ্রণটি ভিত্তি করে তৈরি করেছি।

উপাদানগুলি খুব সহজেই যুক্ত করা হয়:

Entity e = new Entity(); //No templates/archetypes yet.
e.AddComponent(new HealthComponent(100));

এবং নাম, টাইপ, বা (যদি স্বাস্থ্য ও অবস্থানের মতো সাধারণ বিষয়গুলি) দ্বারা সম্পত্তি দ্বারা অনুসন্ধান করা যেতে পারে:

e["Health"] //This, unfortunately, is a bit slower since it requires a dict search
e.GetComponent<HealthComponent>()
e.Health

এবং সরানো হয়েছে:

e.RemoveComponent<HealthComponent>();

তথ্যগুলি আবারও বৈশিষ্ট্য দ্বারা অ্যাক্সেস করা হয়:

e.MaxHP

যা উপাদান-সঞ্চিত; এইচপি না থাকলে কম ওভারহেড:

public int? MaxHP
{
get
{

    return this.Health.MaxHP; //Error handling returns null if health isn't here. Excluded for clarity
}
set
{
this.Health.MaxHP = value;
}

টাইপিংয়ের বিশাল পরিমাণটি ভিএস-তে ইনটেলিসেন্স দ্বারা সহায়তাপ্রাপ্ত তবে বেশিরভাগ অংশের জন্য খুব কম টাইপিং রয়েছে - আমি যে জিনিসটির সন্ধান করছিলাম।

পর্দার আড়ালে, আমি একটি সঞ্চয় করছি Dictionary<Type, Component>এবং নাম যাচাইয়ের জন্য পদ্ধতিটি Componentsওভাররাইড করছি ToString। আমার আসল নকশাটি প্রাথমিকভাবে নাম এবং জিনিসগুলির জন্য স্ট্রিং ব্যবহার করে, তবে এটি কাজ করার জন্য একটি শূকর হয়ে উঠেছে (ওহ দেখুন, আমাকে সমস্ত জায়গাতেই কাস্ট করতে হবে পাশাপাশি বৈশিষ্ট্যগুলিতে অ্যাক্সেসের সহজতাও নেই)।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.